.net 4.0的环境下使用SmtpClient发送邮件,带有附件。碰到这个恶心的Exception
System.FormatException: An invalid character was found in the mail header:
查了两天,终于解决了,是.Net自身的bug,据说后续版本是有解决的(估计.net 4.5以后)。
这里贴出解决方案:
public static Attachment CreateAttachment(Stream attachmentFile, string displayName, string contentType, string attachmentFilePath) { var currentCulture = Thread.CurrentThread.CurrentCulture;//.net4.0 bug, var attachment = new Attachment(attachmentFile, displayName); try { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; attachment.ContentType = new ContentType(contentType); attachment.ContentDisposition.CreationDate = File.GetCreationTime(attachmentFilePath); attachment.ContentDisposition.ModificationDate = File.GetLastWriteTime(attachmentFilePath); attachment.ContentDisposition.ReadDate = File.GetLastAccessTime(attachmentFilePath); attachment.TransferEncoding = TransferEncoding.Base64; attachment.NameEncoding = Encoding.UTF8; string encodedAttachmentName = Convert.ToBase64String(Encoding.UTF8.GetBytes(displayName)); encodedAttachmentName = SplitEncodedAttachmentName(encodedAttachmentName); attachment.Name = encodedAttachmentName; } finally { Thread.CurrentThread.CurrentCulture = currentCulture; } return attachment; } private static string SplitEncodedAttachmentName(string encoded) { const string encodingtoken = "=?UTF-8?B?"; const string softbreak = "?="; const int maxChunkLength = 30; int splitLength = maxChunkLength - encodingtoken.Length - (softbreak.Length * 2); IEnumerable<string> parts = SplitByLength(encoded, splitLength); string encodedAttachmentName = encodingtoken; foreach (var part in parts) { encodedAttachmentName += part + softbreak + encodingtoken; } encodedAttachmentName = encodedAttachmentName.Remove(encodedAttachmentName.Length - encodingtoken.Length, encodingtoken.Length); return encodedAttachmentName; } private static IEnumerable<string> SplitByLength(string stringToSplit, int length) { while (stringToSplit.Length > length) { yield return stringToSplit.Substring(0, length); stringToSplit = stringToSplit.Substring(length); } if (stringToSplit.Length > 0) { yield return stringToSplit; } }