如何在.net中处理Mandrill WebHooks

时间:2014-07-11 10:43:10

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

我是一名学生,正在尝试使用mandrill并且说实话,我不知道我在做什么。 我可以使用.net中的mandrill发送电子邮件没问题 我现在想要做的是使用webhooks来捕捉当前的反弹电子邮件,也许更多一次我完成了。

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

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是作为文件还是原始代码传入的?

谢谢你们。 我真的很感激。

4 个答案:

答案 0 :(得分:5)

我正在运行我的Mandrill Webhook处理作为VS中的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";
    }

然后我接受了#34; mandrill_event&#34;的记录(和未记录的)JSON参数。并使用json2csharp.com生成C#属性。我创建了一个名为&#34; MandrillEvent.cs&#34;把它们放在:

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();
        }
    }

你现在有了#34; mandrill_events&#34; JSON对象作为一个正常运行的C#对象!!这有帮助还是需要更多的澄清/帮助?

答案 1 :(得分: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)

希望这将有助于其他人。

答案 2 :(得分:0)

You can also use System.Json to parse the json string into a generic JsonValue using JsonValue.Parse().

All you have to do is modify the response json from Mandrill a little in order to get a valid json document.

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.
}

答案 3 :(得分:0)

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

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

如果您使用的是Web api,则代码将如下所示:

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