将已发送的邮件消息放入“已发送文件夹”

问题描述 投票:0回答:5

我正在使用 Exchange Server 通过 SmtpClient 发送 MailMessages(已成功发送),但希望将我发送的电子邮件转到我发送邮件的电子邮件地址的“已发送文件夹”(未发生)。

using (var mailMessage = new MailMessage("[email protected]", "[email protected]", "subject", "body"))
{
    var smtpClient = new SmtpClient("SmtpHost")
    {
        EnableSsl = false,
        DeliveryMethod = SmtpDeliveryMethod.Network
    };

    // Apply credentials
    smtpClient.Credentials = new NetworkCredential("smtpUsername", "smtpPassword");

    // Send
    smtpClient.Send(mailMessage);
}

我是否缺少一项配置来确保我从“[电子邮件受保护]”发送的所有电子邮件都到达其“已发送文件夹”?

c# smtpclient exchange-server mailmessage
5个回答
21
投票

我已经做到了这一点,因此为了完整起见,这里介绍如何正确执行此操作。使用托管 Exchange Web 服务 ( 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("[email protected]");
em.ToRecipients.Add(new Microsoft.Exchange.WebServices.Data.EmailAddress("[email protected]"));

// Send the email and put it into the SentItems:
em.SendAndSaveCopy(WellKnownFolderName.SentItems);

12
投票

我猜测您的要求主要是让用户了解已发送的电子邮件。已发送邮件文件夹是允许这种情况发生的一种方法。过去,我通过添加一个

BCC Address
解决了这个问题,它可以将电子邮件直接发送到通讯组列表、用户或共享邮箱,从而允许用户查看已发送的内容。

尝试使用某种 Outlook 规则将项目移动到标记为已读的已发送项目文件夹...

using (var mailMessage = new MailMessage(
        "[email protected]", 
        "[email protected]", 
        "",
        "[email protected]",
        "subject", 
        "body"))
{
    var smtpClient = new SmtpClient("SmtpHost")
    {
        EnableSsl = false,
        DeliveryMethod = SmtpDeliveryMethod.Network
    };

    // Apply credentials
    smtpClient.Credentials = new NetworkCredential("smtpUsername", "smtpPassword");

    // Send
    smtpClient.Send(mailMessage);
}

2
投票

我一直在寻找这个问题的答案,但不依赖 Exchange 服务器,而是使用 IMAP 服务器。我不知道这是否超出了问题的范围,但我发现它正在搜索“将已发送的邮件消息放入已发送文件夹”,这首先是我的问题。

在我构建自己的解决方案的基础上,还没有找到直接答案:

我将 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("[email protected]", "[email protected]", "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"); }
    

0
投票
如果您希望将已发送的邮件保存在“已发送邮件”文件夹中,则需要从 Outlook 发送邮件。此文件夹是 Outlook(和许多其他邮件客户端)概念,而不是 SMTP 概念。

您可以使用 Outlook Automation API 要求 Outlook 创建电子邮件并发送。


0
投票
我在使用

MailKit 时遇到了与 SMTP 服务器相同的问题,

发送前需要保存邮件:

private static async Task SaveMessageAsync(MimeMessage message, CancellationToken cancellationToken) { using var client = new ImapClient(); await client.ConnectAsync("host-address-of-server", 143, SecureSocketOptions.Auto, cancellationToken); await client.AuthenticateAsync("[email protected]", "somePassword", cancellationToken); var sentFolder = client.GetFolder(SpecialFolder.Sent); if (sentFolder == null) { var personalFolder = client.GetFolder(client.PersonalNamespaces[0]); sentFolder = await personalFolder.GetSubfolderAsync(nameof(SpecialFolder.Sent), cancellationToken); } await sentFolder.OpenAsync(FolderAccess.ReadWrite, cancellationToken); await sentFolder.AppendAsync(message, MessageFlags.Seen, cancellationToken); await client.DisconnectAsync(true, cancellationToken); }
使用它类似:

private async Task SendMessageAsync(MimeMessage message, CancellationToken cancellationToken) { await SaveMessageAsync(message, cancellationToken); using var client = new SmtpClient(); await client.ConnectAsync("host-address-of-server", 25, SecureSocketOptions.Auto, cancellationToken); await client.AuthenticateAsync("[email protected]", "somePassword", cancellationToken); await client.SendAsync(message, cancellationToken); await client.DisconnectAsync(true, cancellationToken); }
附注我使用了答案中代码中的一些代码:

  • MailKit-MimeKit - 如何复制到已发送文件夹
  • Mailkit:发送草稿
© www.soinside.com 2019 - 2024. All rights reserved.