/// <summary> /// Computes the MD5 checksum of the content. /// </summary> /// <remarks> /// Computes the MD5 checksum of the MIME content in its canonical /// format and then base64-encodes the result. /// </remarks> /// <returns>The md5sum of the content.</returns> /// <exception cref="System.InvalidOperationException"> /// The <see cref="ContentObject"/> is <c>null</c>. /// </exception> public string ComputeContentMd5() { if (ContentObject == null) { throw new InvalidOperationException("Cannot compute Md5 checksum without a ContentObject."); } using (var stream = ContentObject.Open()) { byte[] checksum; using (var filtered = new FilteredStream(stream)) { if (ContentType.Matches("text", "*")) { filtered.Add(new Unix2DosFilter()); } using (var md5 = new MD5()) checksum = md5.ComputeHash(filtered); } var base64 = new Base64Encoder(true); var digest = new byte[base64.EstimateOutputLength(checksum.Length)]; int n = base64.Flush(checksum, 0, checksum.Length, digest); return(Encoding.ASCII.GetString(digest, 0, n)); } }
/// <summary> /// Writes the <see cref="MimeKit.Multipart"/> to the specified output stream. /// </summary> /// <remarks> /// Writes the multipart MIME entity and its subparts to the output stream. /// </remarks> /// <param name="options">The formatting options.</param> /// <param name="stream">The output stream.</param> /// <param name="cancellationToken">A cancellation token.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="options"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="stream"/> is <c>null</c>.</para> /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> public override void WriteTo(FormatOptions options, Stream stream, CancellationToken cancellationToken = default(CancellationToken)) { if (Boundary == null) { Boundary = GenerateBoundary(); } base.WriteTo(options, stream, cancellationToken); if (options.International && ContentType.Matches("multipart", "signed")) { // don't reformat the headers or content of any children of a multipart/signed options = options.Clone(); options.HiddenHeaders.Clear(); options.International = false; } var cancellable = stream as ICancellableStream; if (RawPreamble != null && RawPreamble.Length > 0) { WriteBytes(options, stream, RawPreamble, cancellationToken); } var boundary = Encoding.ASCII.GetBytes("--" + Boundary + "--"); if (cancellable != null) { for (int i = 0; i < children.Count; i++) { cancellable.Write(boundary, 0, boundary.Length - 2, cancellationToken); cancellable.Write(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken); children[i].WriteTo(options, stream, cancellationToken); cancellable.Write(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken); } cancellable.Write(boundary, 0, boundary.Length, cancellationToken); cancellable.Write(options.NewLineBytes, 0, options.NewLineBytes.Length, cancellationToken); } else { for (int i = 0; i < children.Count; i++) { cancellationToken.ThrowIfCancellationRequested(); stream.Write(boundary, 0, boundary.Length - 2); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); children[i].WriteTo(options, stream, cancellationToken); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } cancellationToken.ThrowIfCancellationRequested(); stream.Write(boundary, 0, boundary.Length); stream.Write(options.NewLineBytes, 0, options.NewLineBytes.Length); } if (RawEpilogue != null && RawEpilogue.Length > 0) { WriteBytes(options, stream, RawEpilogue, cancellationToken); } }
MimePart CreateAttachment(ContentType contentType, string fileName, Stream stream) { MimePart attachment; if (contentType.Matches("text", "*")) { attachment = new TextPart(contentType.MediaSubtype); foreach (var param in contentType.Parameters) { attachment.ContentType.Parameters.Add(param); } // TODO: should we try to auto-detect charsets if no charset parameter is specified? } else { attachment = new MimePart(contentType); } attachment.FileName = Path.GetFileName(fileName); attachment.IsAttachment = true; if (linked) { attachment.ContentLocation = new Uri(Path.GetFileName(fileName), UriKind.Relative); } LoadContent(attachment, stream); return(attachment); }
ContentType GetContentType(ContentType parent) { ContentType type; for (int i = 0; i < headers.Count; i++) { if (icase.Compare (headers[i].Field, "Content-Type") != 0) continue; if (!ContentType.TryParse (options, headers[i].RawValue, out type)) return new ContentType ("application", "octet-stream"); return type; } if (parent == null || !parent.Matches ("multipart", "digest")) return new ContentType ("text", "plain"); return new ContentType ("message", "rfc822"); }