private static string DecodeField(string str) // 将字段值解码(含非ASCII码时) { string decodedField = ""; string[] fields = str.Split('?'); // 会分成5段,第2段为字符编码,第3段为字节编码,第4段为内容 if (fields.Length == 5) { string encodeType1 = fields[1]; // 字符编码 string encodeType2 = fields[2]; if (encodeType2 == "B") // 如果是Base64编码 { decodedField += MyEncoder.DecodeWithBase64(fields[3], Encoding.GetEncoding(encodeType1)); // 先转为字节数组,再以GBK解码 } else if (encodeType2 == "Q") // 如果是Quoted-printable编码 { decodedField += MyEncoder.DecodeWithQP(fields[3], Encoding.GetEncoding(encodeType1)); } else // 暂时不处理其他类型的编码 { decodedField += (fields[3] + " "); } } else // 不带编码,纯英文 { decodedField = str + " "; } return(decodedField); }
private static string EncodeField(string str) // 将字段值编码(含非ASCII码时) { string utf8Str = MyEncoder.EncodeWithUTF8(str); string base64Str = MyEncoder.EncodeWithBase64(utf8Str); string encodedFieldStr = String.Format("=?UTF-8?B?{0}?=", base64Str); return(encodedFieldStr); }
/* 将字符串转为信体结构 */ public static Body GetBody(string rawStr) { Body body = new Body(); string unfoledRawStr = rawStr.Replace("\r\n ", " ").Replace("\r\n\t", " "); // 展开字段 /* 处理Content-Type和Transfer-Encoding-Type */ string contentTypePattern = "(\r\n|\n)Content-Type:([^;]*);(.*)(\r\n|\n)"; // Content-Type匹配模式 string encodingTypePattern = "(\r\n|\n)Content-Transfer-Encoding:[ ]*(.*)[ ]*(\r\n|\n)"; // Transfer-Encoding-Type匹配模式 Match conmatch = Regex.Match(unfoledRawStr, contentTypePattern); Match enmatch = Regex.Match(unfoledRawStr, encodingTypePattern); if (!conmatch.Success || !enmatch.Success) // 两个必有属性必须匹配成功 { return(body); } string contentTypeStr = conmatch.Groups[2].Value.Trim().Trim('"').ToLower(); // 主属性 string otherAttributes = conmatch.Groups[3].Value; // 其他属性 body.ContentType = GetContentType(contentTypeStr); // 添加Content-Type body.EncodeType = GetEncodingType(enmatch.Groups[2].Value.Trim().Trim('"')); // 添加Transfer-Encoding-Type /* 依据不同的内容类型分别处理 */ if (contentTypeStr.Contains("multipart")) // 混合类型 { body.Boundary = GetBoundary(otherAttributes); body.Charset = GetCharset(otherAttributes); string boundary = "--" + body.Boundary; // 分割字符串 string endBoundary = "--" + body.Boundary + "--"; // 结尾字符串 string[] parts = Regex.Split(rawStr.Replace(endBoundary, boundary), boundary); // 按边界切割 /* 处理每个子部分 */ for (int i = 1; i < parts.Length; i++) // 忽略第一部分,因为是信头 { if (parts[i] == "\r\n" || parts[i] == "\r\n\r\n" || parts[i] == "") // 跳过无意义的部分 { continue; } body.SubBodies.Add(GetBody(parts[i])); // 递归处理子信体 } } else if (contentTypeStr.Contains("text")) // 文本类型 { body.Charset = GetCharset(otherAttributes); string[] strs = Regex.Split(rawStr, "\r\n\r\n"); string data = ""; for (int i = 1; i < strs.Length; i++) // 跳过信头 { if (strs[i] == "\r\n" || strs[i] == "\r\n\r\n" || strs[i] == "") // 跳过无意义的部分 { continue; } string contentStr; switch (body.EncodeType) // 依据不同编码进行解码 { case Transfer_Encoding.Base64: contentStr = strs[i].Replace("\r\n", ""); // 去除所有换行标记 data += (MyEncoder.DecodeWithBase64(contentStr, body.Charset) + "\n"); break; case Transfer_Encoding.Quoted_Printable: strs[i] += "\r\n"; // 每段结尾补一个\r\n,以避免QP编码换行标志被破坏 contentStr = strs[i].Replace("=\r\n", "").Replace("\r\n", ""); // 去除所有换行标记 data += (MyEncoder.DecodeWithQP(contentStr, body.Charset) + "\n"); break; case Transfer_Encoding.Bit8: contentStr = strs[i].Replace("\r\n", ""); // 去除所有换行标记 data += (MyEncoder.DecodeWithBit8(contentStr, body.Charset) + "\n"); break; case Transfer_Encoding.Bit7: contentStr = strs[i].Replace("\r\n", ""); // 去除所有换行标记 data += (contentStr + "\n"); break; default: contentStr = strs[i].Replace("\r\n", ""); // 去除所有换行标记 data += (contentStr + "\n"); break; } } body.Data = body.Charset.GetBytes(data); } else if (contentTypeStr.Contains("application")) // 应用类型 { body.Name = GetName(otherAttributes); body.Disposition = GetDisposition(rawStr); string[] paras = Regex.Split(rawStr, "\r\n\r\n"); byte[] data; switch (body.EncodeType) // 依据不同编码进行解码 { case Transfer_Encoding.Base64: data = MyEncoder.DecodeWithBase64(paras[1].Replace("\r\n", "")); break; case Transfer_Encoding.Quoted_Printable: data = MyEncoder.DecodeWithQP(paras[1].Replace("=\r\n", "").Replace("\r\n", "")); break; case Transfer_Encoding.Bit8: data = MyEncoder.DecodeWithBit8(paras[1].Replace("\r\n", "")); break; case Transfer_Encoding.Bit7: data = Encoding.Default.GetBytes(paras[1].Replace("\r\n", "")); break; default: data = Encoding.Default.GetBytes(paras[1].Replace("\r\n", "")); break; } body.Data = data; } else if (contentTypeStr.Contains("image")) // 图片类型 { body.Name = GetName(otherAttributes); string[] paras = Regex.Split(rawStr, "\r\n\r\n"); byte[] data; switch (body.EncodeType) // 依据不同编码进行解码 { case Transfer_Encoding.Base64: data = MyEncoder.DecodeWithBase64(paras[1].Replace("\r\n", "")); break; case Transfer_Encoding.Quoted_Printable: data = MyEncoder.DecodeWithQP(paras[1].Replace("=\r\n", "").Replace("\r\n", "")); break; case Transfer_Encoding.Bit8: data = MyEncoder.DecodeWithBit8(paras[1].Replace("\r\n", "")); break; case Transfer_Encoding.Bit7: data = Encoding.Default.GetBytes(paras[1].Replace("\r\n", "")); break; default: data = Encoding.Default.GetBytes(paras[1].Replace("\r\n", "")); break; } body.Data = data; } else { } return(body); }
private static string BodyToStr(Body body) // 将信体转为字符串 { string bodyStr = ""; // Content-Type if (body.IsMulti) { bodyStr += String.Format("Content-Type: {0};\r\n\tboundary=\"{1}\"\r\n", GetContentTypeStr(body.ContentType), body.Boundary); } else if (body.IsAttachment) { bodyStr += String.Format("Content-Type: {0};\r\n\tname=\"{1}\"\r\n", GetContentTypeStr(body.ContentType), body.Name); } else { bodyStr += String.Format("Content-Type: {0};\r\n\tcharset=\"{1}\"\r\n", GetContentTypeStr(body.ContentType), "UTF-8"); } // Content-Transfer-Encoding if (!body.IsMulti) { bodyStr += String.Format("Content-Transfer-Encoding: base64\r\n"); } // Other Attributes if (body.IsAttachment) { bodyStr += String.Format("Content-Disposition: attachment; filename=\"{0}\"\r\n", body.Name); } /* 构建邮件体 */ if (body.IsMulti) { foreach (Body subBody in body.SubBodies) { bodyStr += String.Format("\r\n--{0}\r\n", body.Boundary); // 添加起头 bodyStr += BodyToStr(subBody); } bodyStr += String.Format("\r\n--{0}--\r\n", body.Boundary); // 添加结尾 } else { string base64Data = MyEncoder.EncodeWithBase64(body.Data); // 编码为base64 string dstStr = ""; dstStr += "\r\n"; for (int i = 0; i < base64Data.Length; i += 75) // 保证每行不超过80字符 { if (i + 75 < base64Data.Length) { dstStr += base64Data.Substring(i, 75) + "\r\n"; } else { dstStr += base64Data.Substring(i, base64Data.Length - i) + "\r\n"; } } dstStr += "\r\n"; bodyStr += dstStr; } return(bodyStr); }
/* 发送邮件 */ private void SendBtnClick(object sender, RoutedEventArgs e) { if (ToTextBox.Text != null & DataTextBox.Text != null) { smtp.Init(smtpServerAddr, 25); // 初始化并登录邮箱 smtp.Login(user, pwd); Email email = new Email(); // 创建一封邮件 /* 信头 */ Heading head = new Heading() { From = user, To = ToTextBox.Text, Subject = SubjectTextBox.Text == null ? "Unknown" : SubjectTextBox.Text, // TODO: 提取部分Data作为subject }; /* 信体 */ Body body = new Body(); UTF8Encoding utf8 = new UTF8Encoding(); byte[] b = utf8.GetBytes(MyEncoder.EncodeWithUTF8(DataTextBox.Text)); Body textBody = new Body() { ContentType = Content_Type.Text_Plain, Data = b }; if (attachments.Count != 0) { body.ContentType = Content_Type.Multi_Mixed; body.SubBodies.Add(textBody); foreach (Attachment attachment in attachments) { Body attachBody = new Body() { ContentType = attachment.ContentType, Name = attachment.Name, Data = attachment.Data, }; body.SubBodies.Add(attachBody); } attachments.Clear(); SendAttachmentListBox.ItemsSource = null; SendAttachmentListBox.ItemsSource = attachments; } else { body = textBody; } email.Head = head; email.Content = body; smtp.SendEmail(email); // 发送邮件 smtp.Close(); } else { // 显示错误 } }