【问题标题】:Send Attachments with Amazon-SES使用 Amazon-SES 发送附件
【发布时间】:2017-06-23 05:19:04
【问题描述】:

我正在寻找一个可以使用 Amazon-SES 发送附件的 C# 示例。

在阅读 Amazon-SES 现在支持发送附件后,我正在搜索 C# 示例但找不到。

【问题讨论】:

    标签: c# .net amazon-web-services amazon-ses


    【解决方案1】:

    我认为使用AWS SDK for .NETMimeKit 是非常简单和干净的解决方案。您可以通过 SES API(而不是 SMTP)发送带有附件的电子邮件。

    您可以将 MimeMessage 直接写入 MemoryStream,然后与 SES SendRawEmail 一起使用:

    using Amazon.SimpleEmail;
    using Amazon.SimpleEmail.Model;
    using Amazon;
    using Amazon.Runtime;
    using MimeKit;
    
    private static BodyBuilder GetMessageBody()
    {
        var body = new BodyBuilder()
        {
            HtmlBody = @"<p>Amazon SES Test body</p>",
            TextBody = "Amazon SES Test body",
        };
        body.Attachments.Add(@"c:\attachment.txt");
        return body;
    }
    
    private static MimeMessage GetMessage()
    {
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("Foo Bar", "foo@bar.com"));
        message.To.Add(new MailboxAddress(string.Empty, "foobar@example.com"));
        message.Subject = "Amazon SES Test";
        message.Body = GetMessageBody().ToMessageBody();
        return message;
    }
    
    private static MemoryStream GetMessageStream()
    {
        var stream = new MemoryStream();
        GetMessage().WriteTo(stream);
        return stream;
    }
    
    private void SendEmails()
    {
        var credentals = new BasicAWSCredentials("<aws-access-key>", "<aws-secret-key>");
    
        using (var client = new AmazonSimpleEmailServiceClient(credentals, RegionEndpoint.EUWest1))
        {
            var sendRequest = new SendRawEmailRequest { RawMessage = new RawMessage(GetMessageStream()) };
            try
            {
                var response = client.SendRawEmail(sendRequest);
                Console.WriteLine("The email was sent successfully.");
            }
            catch (Exception e)
            {
                Console.WriteLine("The email was not sent.");
                Console.WriteLine("Error message: " + e.Message);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:
      public Boolean SendRawEmail(String from, String to, String cc, String Subject, String text, String html, String replyTo, string attachPath)
          {
              AlternateView plainView = AlternateView.CreateAlternateViewFromString(text, Encoding.UTF8, "text/plain");
              AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, Encoding.UTF8, "text/html");
      
              MailMessage mailMessage = new MailMessage();
      
              mailMessage.From = new MailAddress(from);
      
              List<String> toAddresses = to.Replace(", ", ",").Split(',').ToList();
      
              foreach (String toAddress in toAddresses)
              {
                  mailMessage.To.Add(new MailAddress(toAddress));
              }
      
              List<String> ccAddresses = cc.Replace(", ", ",").Split(',').Where(y => y != "").ToList();
      
              foreach (String ccAddress in ccAddresses)
              {
                  mailMessage.CC.Add(new MailAddress(ccAddress));
              }
      
              mailMessage.Subject = Subject;
              mailMessage.SubjectEncoding = Encoding.UTF8;
      
              if (replyTo != null)
              {
                  mailMessage.ReplyToList.Add(new MailAddress(replyTo));
              }
      
              if (text != null)
              {
                  mailMessage.AlternateViews.Add(plainView);
              }
      
              if (html != null)
              {
                  mailMessage.AlternateViews.Add(htmlView);
              }
      
              if (attachPath.Trim() != "")
              {
                  if (System.IO.File.Exists(attachPath))
                  {
                      System.Net.Mail.Attachment objAttach = new System.Net.Mail.Attachment(attachPath);
                      objAttach.ContentType = new ContentType("application/octet-stream"); 
                      System.Net.Mime.ContentDisposition disposition = objAttach.ContentDisposition;
                      disposition.DispositionType = "attachment";
                      disposition.CreationDate = System.IO.File.GetCreationTime(attachPath);
                      disposition.ModificationDate = System.IO.File.GetLastWriteTime(attachPath);
                      disposition.ReadDate = System.IO.File.GetLastAccessTime(attachPath);
                      mailMessage.Attachments.Add(objAttach);
                  }
              }
      
              RawMessage rawMessage = new RawMessage();
      
              using (MemoryStream memoryStream = ConvertMailMessageToMemoryStream(mailMessage))
              {
                  rawMessage.WithData(memoryStream);
              }
      
              SendRawEmailRequest request = new SendRawEmailRequest();
              request.WithRawMessage(rawMessage);
      
              request.WithDestinations(toAddresses);
              request.WithSource(from);
      
              AmazonSimpleEmailService ses = AWSClientFactory.CreateAmazonSimpleEmailServiceClient(ConfigurationManager.AppSettings.Get("AccessKeyId"), ConfigurationManager.AppSettings.Get("SecretKeyId"));
      
              try
              {
                  SendRawEmailResponse response = ses.SendRawEmail(request);
                  SendRawEmailResult result = response.SendRawEmailResult;
                  return true;
              }
              catch (AmazonSimpleEmailServiceException ex)
              {
                  return false;
              }
          }
          public static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
          {
              Assembly assembly = typeof(SmtpClient).Assembly;
              Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
              MemoryStream fileStream = new MemoryStream();
              ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
              object mailWriter = mailWriterContructor.Invoke(new object[] { fileStream });
              MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
              sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);
              MethodInfo closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
              closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
              return fileStream;
          }
      

      发现here

      更新:.NET 4.5 中的方法签名已更改,这破坏了上述内容: Getting System.Net.Mail.MailMessage as a MemoryStream in .NET 4.5 beta

      【讨论】:

      • 如果您的项目使用 .NET Framework 3.5,这将是唯一可行的解​​决方案。 MimeKit 最新版本不支持 .NET Framework 3.5
      【解决方案3】:

      这是一个使用 MimeKit 的非常简单的实现

      using Amazon;
      using Amazon.SimpleEmail;
      using Amazon.SimpleEmail.Model;
      using MimeKit;
      using System.IO;
      
      namespace SendEmailWithAttachments
      {
       class Program
       {
          static void Main(string[] args)
          {
              //Remember to enter your (AWSAccessKeyID, AWSSecretAccessKey) if not using and IAM User with credentials assigned to your instance and your RegionEndpoint
              using (var client = new AmazonSimpleEmailServiceClient("YourAWSAccessKeyID", "YourAWSSecretAccessKey", RegionEndpoint.USEast1))
              using (var messageStream = new MemoryStream())
              {
                  var message = new MimeMessage();
                  var builder = new BodyBuilder() { TextBody = "Hello World" };
      
                  message.From.Add(new MailboxAddress("FROMADDRESS@TEST.COM"));
                  message.To.Add(new MailboxAddress("TOADDRESS@TEST.COM"));
                  message.Subject = "Hello World";
      
                  //I'm using the stream method, but you don't have to.
                  using (FileStream stream = File.Open(@"Attachment1.pdf", FileMode.Open)) builder.Attachments.Add("Attachment1.pdf", stream);
                  using (FileStream stream = File.Open(@"Attachment2.pdf", FileMode.Open)) builder.Attachments.Add("Attachment2.pdf", stream);
      
                  message.Body = builder.ToMessageBody();
                  message.WriteTo(messageStream);
      
                  var request = new SendRawEmailRequest()
                  {
                      RawMessage = new RawMessage() { Data = messageStream }
                  };
      
                  client.SendRawEmail(request);
              }
          }
        }
      }
      

      我的代码库中有代码https://github.com/gianluis90/amazon-send-email

      【讨论】:

        【解决方案4】:

        您也可以设置 IIS SMTP 以通过 SES 进行中继。

        你需要安装stunnelset it up

        然后您可以设置 IIS SMTP Smart Host 和其他一些选项,它会通过 SES 中继您的电子邮件。

        以上链接要点的说明:

        指令取自Amazon's docs,并根据需要进行修改。

        1。安装stunnel

        • stunnel 的下载download page
        • 使用默认选项运行安装程序,通过回答问题创建自签名证书
        • 在记事本中打开c:\program files (x86)\stunnel\stunnel.conf文件
        • 清除所有服务器配置(在Example SSL server mode services 部分下,不会有client = yes 行)
        • 创建新的客户端配置:

        [smtp-tls-wrapper]
        接受 = 127.0.0.1:2525
        客户=是
        连接 = email-smtp.us-east-1.amazonaws.com:465

        • 启动 stunnel.exe 并确保不报告任何错误(您将获得一个小系统托盘图标)
        • 如果成功,您可以选择安装为服务,方法是在命令行运行stunnel.exe -install(注意这会安装服务但不会启动它,所以启动它)
        • 测试连接,在 cmd 行运行 telnet localhost 2525,您应该会看到来自亚马逊服务器的 SMTP 响应(如果未安装 telnet,请在 Server Manager / Features / Add Feature 中添加该功能 )

        2。配置 IIS SMTP

        • 将智能主机设置为[127.0.0.1](包括括号)
        • Outbound Connections 部分,将传出端口设置为 2525(如 stunnel.conf 文件)
        • 出站安全部分,将身份验证信息设置为您的 Amazon SMTP 凭证,将其设置为基本身份验证(注意:请勿选中 TLS 复选框)

        【讨论】:

        【解决方案5】:

        我不确定这是否是您要查找的内容,但这是我能找到的关于该主题的唯一资源。我也希望有更好的答案来回答这个问题。

        http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/

        它说明了如何使用它,但非常神秘,至少对我来说是这样。

        那里有更好的指南吗?

        【讨论】:

          【解决方案6】:

          我也需要这方面的帮助,但到目前为止,我发现您需要发送多部分 MIME 消息,附件以 base64 编码。

          【讨论】:

            【解决方案7】:

            我认为您需要按照this link 上的说明进行操作。 Amazon 不允许您添加附件或其他更复杂的消息类型(iCalendar 事件)。本质上,您需要通过字符串构建和操作来手工制作消息正文。

            目前,我在旧系统上为 iCalendar 格式的电子邮件执行此操作。这有点让人头疼,但是如果您阅读 RFC 2822,它会非常清楚地告诉您格式是什么。特别要注意的事项:

            • 数据的Base64编码
            • MIME 类型
            • 确保您的多部分边界匹配(并且是唯一的)
            • 某些行之后的换行符 (\n) 数的问题

            祝你好运。我不知道是否有一个开放的库可以在 C# 中为你做这种事情。如果您能找到,请尝试使用它,因为处理 RFC 的复杂性应该有关于血压升高和脱发的医疗通知。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-12-31
              • 2017-08-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多