云计算 频道

文图实战:在Windows Azure中处理邮件

  是的,就是这么简单。因为我使用的是 SendGrid 的免费服务,每天最多只能发送200封邮件,并且没有独立IP地址,因为我发送出去的邮件很可能不能通过垃圾邮件过滤器。

  使用W orker 角色接收邮件

  在C#下很难找到一个好用且免费的接收邮件的开发库,我使用了 Eric Daugherty 的 C# Email Server (CSES)接收邮件,并添加了 SharpMime 工具来处理解码有附件的MIME邮件,接收邮件的代码最主要要完成两件事:

  1、在 OnStart() 中启动一个 TcpListener 监听合适的端口。

  2、在 Run() 中启动一个循环,处理每个入站的邮件,即将邮件保存到Blob存储并进行回复。

  下面是我们最初的SMTP处理程序(CSES的一部分)和在正确端口上启动 TcpListener 的代码(来自 OnStart() 的调用):

    listener = new TcpListener(IPAddress.Any,
        RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[
"SmtpIn"].IPEndpoint.Port);
    processor
= new SMTPProcessor(RoleEnvironment.GetConfigurationSettingValue("DomainName"),
        
new RecipientFilter(), new MessageSpool());
    listener.Start();

 

  注意我使用了运行时API确定正确的端口。

 

  下面是简单的入站TCP连接异步处理代码(来自run()的调用):

    var mutex = new ManualResetEvent(false);
    
while (true)
    {
        mutex.Reset();
        listener.BeginAcceptSocket((ar)
=>
            {
                mutex.Set();
                processor.ProcessConnection(listener.EndAcceptSocket(ar));
            },
null);
        mutex.WaitOne();
    }

 

  下面是处理入站邮件的代码:

    // make a container, with public access to blobs
    var id
= Guid.NewGuid().ToString().Replace("-", null);
    var container
= account.CreateCloudBlobClient().GetContainerReference(id);
    container.Create();
    container.SetPermissions(
new BlobContainerPermissions() { PublicAccess=BlobContainerPublicAccessType.Blob });
    
    
// parse the message
    var msg
= new SharpMessage(new MemoryStream(Encoding.ASCII.GetBytes(message.Data)),
        SharpDecodeOptions.AllowAttachments | SharpDecodeOptions.AllowHtml | SharpDecodeOptions.DecodeTnef);
    
    
// create a permalink-style name for the blob
    var permalink
= Regex.Replace(Regex.Replace(msg.Subject.ToLower(), @"[^a-z0-9]", "-"), "--+", "-").Trim('-');
    if (string.IsNullOrEmpty(permalink))
    {
        
// in case there's no subject
        permalink = "message";
    }
    var bodyBlob
= container.GetBlobReference(permalink);
    
// set the CDN to cache the object for 2 hours
    bodyBlob.Properties.CacheControl
= "max-age=7200";
    
    
// replaces references to attachments with the URL of where we'll put them
    msg.SetUrlBase(Utility.GetCdnUrlForUri(bodyBlob.Uri) + "/[Name]");
    
    
// save each attachment in a blob, setting the appropriate content type
    foreach (SharpAttachment attachment in msg.Attachments)
    {
        var blob
= container.GetBlobReference(permalink + "/" + attachment.Name);
        blob.Properties.ContentType
= attachment.MimeTopLevelMediaType + "/" + attachment.MimeMediaSubType;
        blob.Properties.CacheControl
= "max-age=7200";
        attachment.Stream.Position
= 0;
        blob.UploadFromStream(attachment.Stream);
    }
    
// add the footer and save the body to the blob
    SaveBody(msg, bodyBlob, message, container, permalink);
0
相关文章