如何在 .net 中处理 Mandrill WebHooks
Posted
技术标签:
【中文标题】如何在 .net 中处理 Mandrill WebHooks【英文标题】:How To Handle Mandrill WebHooks in .net 【发布时间】: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 是作为文件还是原始代码传入?
谢谢各位。 我真的很感激。
【问题讨论】:
【参考方案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://***.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();
【讨论】:
以上是关于如何在 .net 中处理 Mandrill WebHooks的主要内容,如果未能解决你的问题,请参考以下文章
Mandrill Mailchimp 如何在电子邮件正文中嵌入图像
MailChimp (Mandrill) for .NET 为啥电子邮件包含图像?
如何使用 Parse 和 Mandrill 发送电子邮件通知?