32

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

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

4

7 回答 7

27

我认为使用适用于 .NETMimeKit的 AWS 开发工具包是非常简单且干净的解决方案。您可以通过 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);
        }
    }
}
于 2016-01-07T17:39:16.027 回答
12
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;
    }

发现这里

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

于 2012-03-08T16:45:18.310 回答
5

这是一个使用 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

于 2017-06-22T21:19:04.353 回答
1

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

您需要安装stunnel并进行设置

然后您可以设置 IIS SMTP智能主机和其他一些选项,它将通过 SES 中继您的电子邮件。

以上链接要点的说明:

说明取自亚马逊文档并根据需要进行修改。

1.安装通道

  • stunnel 的 下载页面下载
  • 使用默认选项运行安装程序,通过回答问题创建自签名证书
  • 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 文件)
  • Outbound Security部分,将身份验证信息设置为您的 Amazon SMTP 凭证,将其设置为基本身份验证(注意:不要检查 TLS 复选框)
于 2012-08-02T13:08:49.030 回答
0

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

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

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

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

于 2012-02-27T18:25:10.327 回答
0

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

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

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

那里有更好的指南吗?

于 2011-07-25T20:51:55.897 回答
0

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

于 2011-09-08T14:47:29.140 回答