// sends a multipart mail to the server void SendMultipartMail(MailMessageWrapper msg) { // generate the boundary between attachments string boundary = MailUtil.GenerateBoundary(); // set the Content-Type header to multipart/mixed string bodyContentType = msg.Header.ContentType; msg.Header.ContentType = String.Concat("multipart/mixed;\r\n boundary=", boundary); // write the header smtp.WriteHeader(msg.Header); // write the first part text part // before the attachments smtp.WriteBoundary(boundary); MailHeader partHeader = new MailHeader(); partHeader.ContentType = bodyContentType; // Add all the custom headers to body part as specified in //Fields property of MailMessageWrapper //Remove fields specific for authenticating to SMTP server. //Need to incorporate AUTH command in SmtpStream to handle //Authorization info. Its a temporary fix for Bug no 68829. //Will dig some more on SMTP AUTH command, and then implement //Authorization. - Sanjay if (msg.Fields.Data ["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"] != null) { msg.Fields.Data.Remove("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"); } if (msg.Fields.Data ["http://schemas.microsoft.com/cdo/configuration/sendusername"] != null) { msg.Fields.Data.Remove("http://schemas.microsoft.com/cdo/configuration/sendusername"); } if (msg.Fields.Data ["http://schemas.microsoft.com/cdo/configuration/sendpassword"] != null) { msg.Fields.Data.Remove("http://schemas.microsoft.com/cdo/configuration/sendpassword"); } partHeader.Data.Add(msg.Fields.Data); smtp.WriteHeader(partHeader); // FIXME: probably need to use QP or Base64 on everything higher // then 8-bit .. like utf-16 smtp.WriteBytes(msg.BodyEncoding.GetBytes(msg.Body)); smtp.WriteBoundary(boundary); // now start to write the attachments for (int i = 0; i < msg.Attachments.Count; i++) { MailAttachment a = (MailAttachment)msg.Attachments[i]; FileInfo fileInfo = new FileInfo(a.Filename); MailHeader aHeader = new MailHeader(); aHeader.ContentType = String.Concat(MimeTypes.GetMimeType(fileInfo.Name), "; name=\"", fileInfo.Name, "\""); aHeader.ContentDisposition = String.Concat("attachment; filename=\"", fileInfo.Name, "\""); aHeader.ContentTransferEncoding = a.Encoding.ToString(); smtp.WriteHeader(aHeader); // perform the actual writing of the file. // read from the file stream and write to the tcp stream FileStream ins = fileInfo.OpenRead(); // create an apropriate encoder IAttachmentEncoder encoder; if (a.Encoding == MailEncoding.UUEncode) { encoder = new UUAttachmentEncoder(644, fileInfo.Name); } else { encoder = new Base64AttachmentEncoder(); } encoder.EncodeStream(ins, smtp.Stream); ins.Close(); smtp.WriteLine(""); // if it is the last attachment write // the final boundary otherwise write // a normal one. if (i < (msg.Attachments.Count - 1)) { smtp.WriteBoundary(boundary); } else { smtp.WriteFinalBoundary(boundary); } } }
// Constructor public MailMessageWrapper(MailMessage message) { this.message = message; if (message.From != null) { from = MailAddress.Parse(message.From); header.From = from.ToString(); } if (message.To != null) { to = MailAddressCollection.Parse(message.To); header.To = to.ToString(); } if (message.Cc != null) { cc = MailAddressCollection.Parse(message.Cc); header.Cc = cc.ToString(); } if (message.Bcc != null) { bcc = MailAddressCollection.Parse(message.Bcc); header.Bcc = bcc.ToString(); } // set the subject if (message.Subject != null) { // encode the subject if it needs encoding if (MailUtil.NeedEncoding(message.Subject)) { byte[] subjectBytes = message.BodyEncoding.GetBytes(message.Subject); // encode the subject with Base64 header.Subject = "=?" + message.BodyEncoding.BodyName + "?B?" + Convert.ToBase64String(subjectBytes) + "?="; } else { header.Subject = message.Subject; } } // convert single '.' on a line with ".." to not // confuse the smtp server since the DATA command // is terminated with a '.' on a single line. // this is also according to the smtp specs. if (message.Body != null) { body = message.Body.Replace("\n.\n", "\n..\n"); body = body.Replace("\r\n.\r\n", "\r\n..\r\n"); } // set the Contet-Base header if (message.UrlContentBase != null) { header.ContentBase = message.UrlContentBase; } // set the Contet-Location header if (message.UrlContentLocation != null) { header.ContentLocation = message.UrlContentLocation; } // set the content type switch (message.BodyFormat) { case MailFormat.Html: header.ContentType = String.Concat("text/html; charset=\"", message.BodyEncoding.BodyName, "\""); break; case MailFormat.Text: header.ContentType = String.Concat("text/plain; charset=\"", message.BodyEncoding.BodyName, "\""); break; default: header.ContentType = String.Concat("text/html; charset=\"", message.BodyEncoding.BodyName, "\""); break; } // set the priority as in the same way as .NET sdk does switch (message.Priority) { case MailPriority.High: header.Importance = "high"; break; case MailPriority.Low: header.Importance = "low"; break; case MailPriority.Normal: header.Importance = "normal"; break; default: header.Importance = "normal"; break; } // .NET sdk allways sets this to normal header.Priority = "normal"; // Set the mime version header.MimeVersion = "1.0"; // Set the transfer encoding if (message.BodyEncoding is ASCIIEncoding) { header.ContentTransferEncoding = "7bit"; } else { header.ContentTransferEncoding = "8bit"; } // Add Date header, we were missing earlier 27/08/04 // RFC822 requires date to be in format Fri, 27 Aug 2004 20:13:20 +0530 //DateTime.Now gives in format 8/27/2004 8:13:00 PM // Need to explore further dateTime formats available or do we need // to write a function to convert. //header.Data.Add ("Date", DateTime.Now.ToString()); // Add the custom headers foreach (string key in message.Headers.Keys) { header.Data[key] = (string)this.message.Headers[key]; } }