【问题标题】:How To Handle Mandrill WebHooks in .net如何在 .net 中处理 Mandrill WebHooks
【发布时间】:2014-09-01 23:13:42
【问题描述】:

我是一名试图与山魈一起工作的学生,老实说,我不知道自己在做什么。 我可以在 .net 中使用 mandrill 发送电子邮件 我现在想做的是使用 webhook 来捕获退回的电子邮件,一旦我完成了可能会更多。

这是我到目前为止的代码(来自互联网)

public ActionResult HandleMandrillWebhook(FormCollection fc)
    {
        string json = fc["mandrill_events"];

        var events = JsonConvert.DeserializeObject<IEnumerable<Mandrill.MailEvent>>(json);
        foreach (var mailEvent in events)
        {
            var message = mailEvent.Msg;
            // ... Do stuff with email message here...
        }

        // MUST do this or Mandrill will not accept your webhook!
        return new HttpStatusCodeResult((int)HttpStatusCode.OK);

然后我就有了这个

public class MailEvent
{
    [JsonProperty(PropertyName = "ts")]
    public string TimeStamp { get; set; }

    [JsonProperty(PropertyName = "event")]
    public string Event { get; set; }

    [JsonProperty(PropertyName = "msg")]
    public Message Msg { get; set; }
}

public class Message
{
    [JsonProperty(PropertyName = "raw_msg")]
    public string RawMessage { get; set; }

    [JsonProperty(PropertyName = "headers")]
    public Header Header { get; set; }

    [JsonProperty(PropertyName = "text")]
    public string Text { get; set; }

    [JsonProperty(PropertyName = "html")]
    public string Html { get; set; }

    [JsonProperty(PropertyName = "from_email")]
    public string FromEmail { get; set; }

    [JsonProperty(PropertyName = "from_name")]
    public string FromName { get; set; }

    // Not sure why Mandrill sends an array of arrays here...
    [JsonProperty(PropertyName = "to")]
    public string[][] To { get; set; }

    [JsonProperty(PropertyName = "email")]
    public string Email { get; set; }

    [JsonProperty(PropertyName = "subject")]
    public string Subject { get; set; }

    [JsonProperty(PropertyName = "tags")]
    public string[] Tags { get; set; }

    [JsonProperty(PropertyName = "sender")]
    public string Sender { get; set; }

    [JsonProperty(PropertyName = "dkim")]
    public DKIM DKIM { get; set; }

    [JsonProperty(PropertyName = "spf")]
    public SPF SPF { get; set; }

    [JsonProperty(PropertyName = "spam_report")]
    public SpamReport SpamReport { get; set; }
}

[JsonDictionary()]
public class Header : Dictionary<string, object>
{
    // Need to find a nicer way of doing this... Dictionary<string, object> is kinda dumb
}

public class SpamReport
{
    [JsonProperty(PropertyName = "score")]
    public decimal Score { get; set; }

    [JsonProperty(PropertyName = "matched_rules")]
    public SpamRule[] MatchedRules { get; set; }
}

public class SpamRule
{
    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "score")]
    public decimal Score { get; set; }

    [JsonProperty(PropertyName = "description")]
    public string Description { get; set; }
}

public class DKIM
{
    [JsonProperty(PropertyName = "signed")]
    public bool Signed { get; set; }

    [JsonProperty(PropertyName = "valid")]
    public bool Valid { get; set; }
}

public class SPF
{
    [JsonProperty(PropertyName = "result")]
    public string Result { get; set; }

    [JsonProperty(PropertyName = "detail")]
    public string Detail { get; set; }
}

谁能告诉我如何处理 mandrill webhook 响应。 它在 json 中。

我以前从未做过这样的事情。我错过了很多代码吗? json 是作为文件还是原始代码传入?

谢谢各位。 我真的很感激。

【问题讨论】:

    标签: c# json asp.net-web-api mandrill webhooks


    【解决方案1】:

    我在 VS 中将 Mandrill Webhook 处理作为 API 项目运行,这就是我启动和运行它的方式:

        [HttpPost]
        public string Post()
        {
            /* Every Mandrill webhook uses the same general data format, regardless of the event type. 
             * The webhook request is a standard POST request with a single parameter (currently) - 'mandrill_events'. */
    
            string validJson = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", ""); //"mandrill_events=" is not valid JSON. If you take that out you should be able to parse it. //http://stackoverflow.com/questions/24521326/deserializing-mandrillapp-webhook-response
            List<MandrillEvent> mandrillEventList = JsonConvert.DeserializeObject<List<MandrillEvent>>(validJson);
    
            foreach (MandrillEvent mandrillEvent in mandrillEventList)
            {
                if (mandrillEvent.msg.email != null)
                {
                    DataLayer.ReportingData.EmailSave(mandrillEvent); //Saves MandrillEvent email to database and sets a messageId for datalayer
                }
            } 
    
            foreach (MandrillEvent mandrillEvent in mandrillEventList)
            {
                DataLayer.ReportingData.MandrillEventSave(mandrillEvent); //Saves MandrillEvent object to database
            }
    
            return "DONE";
        }
    

    然后,我获取了“mandrill_event”的记录(和未记录)JSON 参数并使用json2csharp.com 生成C# 属性。我创建了一个名为“MandrillEvent.cs”的类并将它们放在:

    public class SmtpEvent
        {
            public int ts { get; set; }
            public DateTime SmtpTs { get; set; }
            public string type { get; set; }
            public string diag { get; set; }
            public string source_ip { get; set; }
            public string destination_ip { get; set; }
            public int size { get; set; }
            public int smtpId { get; set; } //added for datalayer
        }
    
        public class Msg
        {
            public int ts { get; set; }
            public DateTime MsgTs { get; set; }
            public string _id { get; set; }
            public string state { get; set; }
            public string subject { get; set; }
            public string email { get; set; }
            public List<object> tags { get; set; }
            public List<object> opens { get; set; } //an array of containing an item for each time the message was opened. Each open includes the following keys: "ts", "ip", "location", "ua"
            public List<object> clicks { get; set; } //an array containing an item for each click recorded for the message. Each item contains the following: "ts", "url"
            public List<SmtpEvent> smtp_events { get; set; }
            public List<object> resends { get; set; } //not currently documented on http://help.mandrill.com/entries/58303976-Message-Event-Webhook-format
            public string _version { get; set; }
            public string diag { get; set; } //for bounced and soft-bounced messages, provides the specific SMTP response code and bounce description, if any, received from the remote server
            public int bgtools_code { get; set; } //Is it this? for bounced and soft-bounced messages, a short description of the bounce reason such as bad_mailbox or invalid_domain. (not currently documented but in JSON response)
            public string sender { get; set; }
            public object template { get; set; }
            public string bounce_description { get; set; }
    
            public Msg()
            {
                tags = new List<object>();
                opens = new List<object>();
                clicks = new List<object>();
                smtp_events = new List<SmtpEvent>();
                smtp_events.Add(new SmtpEvent());
                resends = new List<object>();
            }
        }
    
        public class MandrillEvent
        {
            public string @event { get; set; }
            public string _id { get; set; }
            public Msg msg { get; set; }
            public int ts { get; set; }
            public DateTime MandrillEventTs { get; set; }
            public int messageId { get; set; } //added for datalayer
            public List<string> SingleMandrillEventData { get; set; } //added for Reporting
    
            public MandrillEvent()
            {
                SingleMandrillEventData = new List<string>();
                msg = new Msg();
            }
        }
    

    您现在将“mandrill_events”JSON 对象作为功能 C# 对象!这是帮助还是您需要更多说明/帮助?

    【讨论】:

    • 嗨.. hopper... 从现在开始,我一直在寻找类似的代码。请问有没有可能帮我解决这个问题?
    • 我当然可以尝试,Athar。怎么了?
    • 谢谢@Hopper...我已经以某种方式解决了它。如果您可以分享您的代码以与 Mandrill 交互,那就太好了。不然我就得自己写了
    • 这个解决方案曾经对我有用,但突然停止了。其他人有过这种经历吗?
    【解决方案2】:

    似乎所有人给出的代码都是错误的,就好像我们使用 request.form 和任何键一样,我们根本不需要替换。

    代码如下:

    string events_json = HttpContext.Current.Request.Form["mandrill_events"];
    
    var events = **Mandrill.Utilities.JSON.Parse<List<Mandrill.Models.WebHookEvent>>(events_json)**;
    foreach (var mailEvent in events)
    {
        var message = mailEvent.Msg;
        // ... Do stuff with email message here...
    }
    

    在这里您可以看到转换是映射到 WebHookEvent 而不是 MailEvent,如下所示。

    JsonConvert.DeserializeObject<IEnumerable<Mandrill.MailEvent>>(json)
    

    希望这对其他人有所帮助。

    【讨论】:

      【解决方案3】:

      您还可以使用 System.Json 将 json 字符串解析为使用 JsonValue.Parse() 的通用 JsonValue。

      您所要做的就是稍微修改一下 Mandrill 的响应 json 以获得有效的 json 文档。

      string json = HttpContext.Current.Request.Form["mandrill_events"];
      json = json.Replace("mandrill_events=", "");    // Remove invalid json
      json = string.Format("{{Events: {0}}}", json);  // Create valid json element
      var jsonValue = JsonValue.Parse(json);
      
      // Now you can loop through the events
      foreach(var e in jsonValue["Events"])
      {
          var id = (string)e.Value["_id"];
          var event_text = (string)e.Value["event"];
          // etc.
      }
      

      【讨论】:

        【解决方案4】:

        如果您使用的是 Azure http 触发函数,那么代码将如下所示:

        string requestBody = await new StreamReader(req.Body, Encoding.UTF8).ReadToEndAsync();
                     requestBody = requestBody.Replace("mandrill_events=", "");
                      requestBody = System.Web.HttpUtility.UrlDecode(requestBody);
        

        如果你使用 web apis 代码会是这样的:

        var requestBody = Request.HttpContext.Request.Form["mandrill_events"].ToString();
        

        【讨论】:

          猜你喜欢
          • 2014-02-14
          • 2013-10-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-26
          • 1970-01-01
          • 2015-06-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多