正如贾斯汀所说,在 API 中无法将一个 MailMessage 附加到另一个。我使用 SmtpClient 解决了这个问题,将我的内部消息“传递”到一个目录,然后将生成的文件附加到我的外部消息中。这个解决方案不是很吸引人,因为它必须利用文件系统,但它确实完成了工作。如果 SmtpDeliveryMethod 有 Stream 选项,它会更干净。
需要注意的一点是,SmtpClient 在创建消息文件时为 SMTP 信封信息添加了 X-Sender/X-Receiver 标头。如果这是一个问题,您必须在附加之前将它们从消息文件的顶部剥离。
// message to be attached
MailMessage attachedMessage = new MailMessage("bob@example.com"
, "carol@example.com", "Attached Message Subject"
, "Attached Message Body");
// message to send
MailMessage sendingMessage = new MailMessage();
sendingMessage.From = new MailAddress("ted@example.com", "Ted");
sendingMessage.To.Add(new MailAddress("alice@example.com", "Alice"));
sendingMessage.Subject = "Attached Message: " + attachedMessage.Subject;
sendingMessage.Body = "This message has a message attached.";
// find a temporary directory path that doesn't exist
string tempDirPath = null;
do {
tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
} while(Directory.Exists(tempDirPath));
// create temp dir
DirectoryInfo tempDir = Directory.CreateDirectory(tempDirPath);
// use an SmptClient to deliver the message to the temp dir
using(SmtpClient attachmentClient = new SmtpClient("localhost")) {
attachmentClient.DeliveryMethod
= SmtpDeliveryMethod.SpecifiedPickupDirectory;
attachmentClient.PickupDirectoryLocation = tempDirPath;
attachmentClient.Send(attachedMessage);
}
tempDir.Refresh();
// load the created file into a stream
FileInfo mailFile = tempDir.GetFiles().Single();
using(FileStream mailStream = mailFile.OpenRead()) {
// create/add an attachment from the stream
sendingMessage.Attachments.Add(new Attachment(mailStream
, Regex.Replace(attachedMessage.Subject
, "[^a-zA-Z0-9 _.-]+", "") + ".eml"
, "message/rfc822"));
// send the message
using(SmtpClient smtp = new SmtpClient("smtp.example.com")) {
smtp.Send(sendingMessage);
}
mailStream.Close();
}
// clean up temp
mailFile.Delete();
tempDir.Delete();