将已发送的邮件消息放入“已发送文件夹”
-
20-09-2019 - |
题
我正在使用 Exchange Server 通过 SmtpClient 发送 MailMessages(已成功发送),但希望将我发送的电子邮件转到我发送邮件的电子邮件地址的“已发送文件夹”(未发生)。
using (var mailMessage = new MailMessage("fromaddress@blah.com", "toaddress@blah.com", "subject", "body"))
{
var smtpClient = new SmtpClient("SmtpHost")
{
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network
};
// Apply credentials
smtpClient.Credentials = new NetworkCredential("smtpUsername", "smtpPassword");
// Send
smtpClient.Send(mailMessage);
}
我是否缺少一个配置来确保我从“fromaddress@blah.com”发送的所有电子邮件都到达其“已发送”文件夹?
解决方案
我猜你的要求主要是面向周围给用户知名度,电子邮件已经发送的内容。发送邮件文件夹是一个方法,让这种情况发生。在过去,我已经加入了BCC Address
将字面上电子邮件直接发送到要么允许用户回顾一下已经派出通讯组列表,用户或共享邮箱解决了这个问题。
与某种Outlook规则尝试使用此方法将项目移至其发送邮件文件夹标记为已读...
using (var mailMessage = new MailMessage(
"fromaddress@blah.com",
"toaddress@blah.com",
"",
"fromaddress@blah.com",
"subject",
"body"))
{
var smtpClient = new SmtpClient("SmtpHost")
{
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network
};
// Apply credentials
smtpClient.Credentials = new NetworkCredential("smtpUsername", "smtpPassword");
// Send
smtpClient.Send(mailMessage);
}
其他提示
我已经做到了这一点,所以为了完整性这里是如何正确地做到这一点。使用托管交换网络服务(的http:// MSDN。 microsoft.com/en-us/library/dd633709%28EXCHG.80%29.aspx ):
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
// In case you have a dodgy SSL certificate:
System.Net.ServicePointManager.ServerCertificateValidationCallback =
delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};
service.Credentials = new WebCredentials("username", "password", "MYDOMAIN");
service.Url = new Uri("https://exchangebox/EWS/Exchange.asmx");
EmailMessage em = new EmailMessage(service);
em.Subject = "example email";
em.Body = new MessageBody("hello world");
em.Sender = new Microsoft.Exchange.WebServices.Data.EmailAddress("john.smith@example.com");
em.ToRecipients.Add(new Microsoft.Exchange.WebServices.Data.EmailAddress("bob.smith@example.com"));
// Send the email and put it into the SentItems:
em.SendAndSaveCopy(WellKnownFolderName.SentItems);
您需要的,如果你想在“已发送邮件”文件夹中的已发送的邮件从Outlook发送邮件。此文件夹是一个Outlook(和许多其他邮件客户端)的概念,而不是一个SMTP概念。
您可以使用Outlook自动化API问Outlook来创建电子邮件并发送。
我一直在寻找这个问题的答案,但不依赖 Exchange 服务器,而是使用 IMAP 服务器。我不知道这是否超出了问题的范围,但我发现它正在搜索“将已发送的邮件消息放入已发送文件夹”,这首先是我的问题。
在我基于以下内容构建自己的解决方案的任何地方都没有找到直接答案:
- 简单的 IMAP 客户端 在 MSDN 上
- 将 MailMessage 转换为原始文本 在 Stackoverflow 上,这是保存消息的必要步骤。
我将 save 方法实现为 smtpClient 的扩展,而不是 .Send()
我们将使用 .SendAndSaveMessageToIMAP()
.
public static class SmtpClientExtensions
{
static System.IO.StreamWriter sw = null;
static System.Net.Sockets.TcpClient tcpc = null;
static System.Net.Security.SslStream ssl = null;
static string path;
static int bytes = -1;
static byte[] buffer;
static System.Text.StringBuilder sb = new System.Text.StringBuilder();
static byte[] dummy;
/// <summary>
/// Communication with server
/// </summary>
/// <param name="command">The command beeing sent</param>
private static void SendCommandAndReceiveResponse(string command)
{
try
{
if (command != "")
{
if (tcpc.Connected)
{
dummy = System.Text.Encoding.ASCII.GetBytes(command);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new System.ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
ssl.Flush();
buffer = new byte[2048];
bytes = ssl.Read(buffer, 0, 2048);
sb.Append(System.Text.Encoding.ASCII.GetString(buffer));
sw.WriteLine(sb.ToString());
sb = new System.Text.StringBuilder();
}
catch (System.Exception ex)
{
throw new System.ApplicationException(ex.Message);
}
}
/// <summary>
/// Saving a mail message before beeing sent by the SMTP client
/// </summary>
/// <param name="self">The caller</param>
/// <param name="imapServer">The address of the IMAP server</param>
/// <param name="imapPort">The port of the IMAP server</param>
/// <param name="userName">The username to log on to the IMAP server</param>
/// <param name="password">The password to log on to the IMAP server</param>
/// <param name="sentFolderName">The name of the folder where the message will be saved</param>
/// <param name="mailMessage">The message being saved</param>
public static void SendAndSaveMessageToIMAP(this System.Net.Mail.SmtpClient self, System.Net.Mail.MailMessage mailMessage, string imapServer, int imapPort, string userName, string password, string sentFolderName)
{
try
{
path = System.Environment.CurrentDirectory + "\\emailresponse.txt";
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
sw = new System.IO.StreamWriter(System.IO.File.Create(path));
tcpc = new System.Net.Sockets.TcpClient(imapServer, imapPort);
ssl = new System.Net.Security.SslStream(tcpc.GetStream());
ssl.AuthenticateAsClient(imapServer);
SendCommandAndReceiveResponse("");
SendCommandAndReceiveResponse(string.Format("$ LOGIN {1} {2} {0}", System.Environment.NewLine, userName, password));
using (var m = mailMessage.RawMessage())
{
m.Position = 0;
var sr = new System.IO.StreamReader(m);
var myStr = sr.ReadToEnd();
SendCommandAndReceiveResponse(string.Format("$ APPEND {1} (\\Seen) {{{2}}}{0}", System.Environment.NewLine, sentFolderName, myStr.Length));
SendCommandAndReceiveResponse(string.Format("{1}{0}", System.Environment.NewLine, myStr));
}
SendCommandAndReceiveResponse(string.Format("$ LOGOUT{0}", System.Environment.NewLine));
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine("error: " + ex.Message);
}
finally
{
if (sw != null)
{
sw.Close();
sw.Dispose();
}
if (ssl != null)
{
ssl.Close();
ssl.Dispose();
}
if (tcpc != null)
{
tcpc.Close();
}
}
self.Send(mailMessage);
}
}
public static class MailMessageExtensions
{
private static readonly System.Reflection.BindingFlags Flags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
private static readonly System.Type MailWriter = typeof(System.Net.Mail.SmtpClient).Assembly.GetType("System.Net.Mail.MailWriter");
private static readonly System.Reflection.ConstructorInfo MailWriterConstructor = MailWriter.GetConstructor(Flags, null, new[] { typeof(System.IO.Stream) }, null);
private static readonly System.Reflection.MethodInfo CloseMethod = MailWriter.GetMethod("Close", Flags);
private static readonly System.Reflection.MethodInfo SendMethod = typeof(System.Net.Mail.MailMessage).GetMethod("Send", Flags);
/// <summary>
/// A little hack to determine the number of parameters that we
/// need to pass to the SaveMethod.
/// </summary>
private static readonly bool IsRunningInDotNetFourPointFive = SendMethod.GetParameters().Length == 3;
/// <summary>
/// The raw contents of this MailMessage as a MemoryStream.
/// </summary>
/// <param name="self">The caller.</param>
/// <returns>A MemoryStream with the raw contents of this MailMessage.</returns>
public static System.IO.MemoryStream RawMessage(this System.Net.Mail.MailMessage self)
{
var result = new System.IO.MemoryStream();
var mailWriter = MailWriterConstructor.Invoke(new object[] { result });
SendMethod.Invoke(self, Flags, null, IsRunningInDotNetFourPointFive ? new[] { mailWriter, true, true } : new[] { mailWriter, true }, null);
result = new System.IO.MemoryStream(result.ToArray());
CloseMethod.Invoke(mailWriter, Flags, null, new object[] { }, null);
return result;
}
}
所以罗伯特·里德的例子将变成
using (var mailMessage = new MailMessage("fromaddress@blah.com", "toaddress@blah.com", "subject", "body"))
{
//Add an attachment just for the sake of it
Attachment doc = new Attachment(@"filePath");
doc.ContentId = "doc";
mailMessage.Attachments.Add(doc);
var smtpClient = new SmtpClient("SmtpHost")
{
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network
};
// Apply credentials
smtpClient.Credentials = new NetworkCredential("smtpUsername", "smtpPassword");
// Send
smtpClient.SendAndSaveMessageToIMAP(mailMessage, "imap.mail.com", 993, "imapUsername", "imapPassword", "SENT");
}