Как отправить приглашение iCal с помощью Mailgun Rest API (C#)

Я пытаюсь добавить приглашение в календаре в формате iCal к электронному письму, отправленному через MailGun API. Это то, что я имею до сих пор:

var request = new RestRequest();

request.AddParameter("domain", this.domain, ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", contactDetails.SenderAddress);
request.AddParameter("to", contactDetails.RecipientAddress);
request.AddParameter("subject", message.Subject);
request.AddParameter("text", message.TextBody);
request.AddParameter("html", message.HtmlBody);

if (!string.IsNullOrWhiteSpace(message.IcalAttachment))
{
    request.AddFileBytes("attachment", 
                         Encoding.UTF8.GetBytes(message.IcalAttachment), 
                         "invite.ics", 
                         "text/calendar");
}

request.Method = Method.POST;
return request;

Это приводит к тому, что календарь включается в электронное письмо как вложение, а не как альтернативный вид электронного письма. Вложение прекрасно работает в Gmail, однако в Outlook оно выглядит как файл вложения, на котором нужно сначала щелкнуть мышью, а затем согласиться на добавление календаря в календарь Outlook. Есть ли другой способ использовать API REST, чтобы приглашения календаря отправлялись правильно, как альтернативные представления электронной почты?

Чтобы было ясно, я бы отправил приглашение в календарь с помощью.Net. SmtpClient:

var contentType = new ContentType("text/calendar");
if (contentType.Parameters != null)
{
    contentType.Parameters.Add("method", "REQUEST");
    contentType.CharSet = "UTF-8";
}

// this is the same way you add a html view to the message
request.AlternateViews.Add(
    AlternateView.CreateAlternateViewFromString(
        message.IcalAttachment, 
        contentType));

1 ответ

Решение

Отдельное спасибо службе Mailgun за то, что она указала мне правильное направление. Соответствующая часть или их ответ был:

Вы можете использовать конечную точку /message.mime для создания MIME для приглашения в календарь: https://documentation.mailgun.com/api-sending.html

Создать сообщение MIME не так просто, как просто использовать конечную точку / message, но для этого есть несколько библиотек.net. Я использовал MimeKit в этом примере.

var request = new RestRequest();

request.AddParameter("domain", this.domain, ParameterType.UrlSegment);
request.Resource = "{domain}/messages.mime";
request.AddParameter("to", contactDetails.RecipientAddress);
request.AddFile(
    "message", 
    Encoding.UTF8.GetBytes(BuildMimeContent(message)), 
    "message.mime");

request.Method = Method.POST;
return request;

Содержимое MIME, которое я хочу создать, будет содержать составное / смешанное тело, которое, в свою очередь, будет содержать составную часть / альтернативу, а также каждое вложение. Приглашение в календаре будет прикреплено дважды, как альтернативный вид и как вложение. Это поможет в совместимости между различными почтовыми клиентами.

Реализация BuildMimeContent(message) выглядит следующим образом:

// create the alternative views
var textBody = new TextPart("plain") { Text = message.TextBody };
var htmlBody = new TextPart("html") { Text = message.HtmlBody };

// add views to the multipart/alternative
var alternative = new Multipart("alternative");
alternative.Add(textBody);
alternative.Add(htmlBody);

if (!string.IsNullOrWhiteSpace(message.CalendarInvite))
{
    // also add the calendar as an alternative view
    // encoded as base64, but 7bit will also work
    var calendarBody = new TextPart("calendar")
    {
        Text = message.CalendarInvite,
        ContentTransferEncoding = ContentEncoding.Base64
    };

    // most clients wont recognise the alternative view without the 
    // method=REQUEST header
    calendarBody.ContentType.Parameters.Add("method", "REQUEST");
    alternative.Add(calendarBody);
}

// create the multipart/mixed that will contain the multipart/alternative
// and all attachments
var multiPart = new Multipart("mixed") { alternative };
if (!string.IsNullOrWhiteSpace(message.CalendarInvite))
{
    // add the calendar as an attachment
    var calAttachment = new MimePart("application", "ics")
    {
        ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
        ContentTransferEncoding = ContentEncoding.Base64,
        FileName = "invite.ics",
        ContentObject = new ContentObject(GenerateStreamFromString(message.CalendarInvite))
    };

    multiPart.Add(calAttachment);
}

// TODO: Add any other attachements to 'multipart' here.

// build final mime message
var mimeMessage = new MimeMessage();
mimeMessage.From.Add(GetMimeAddress(message.MessageInfo.SenderName, message.MessageInfo.SenderAddress));
mimeMessage.To.Add(GetMimeAddress(message.MessageInfo.RecipientName, message.MessageInfo.RecipientAddress));
mimeMessage.Subject = message.Subject;
mimeMessage.Body = multiPart;

// parse and return mime message
return mimeMessage.ToString();

Предупреждение для людей, тестирующих с Office 365

Office365 очень требователен к проверке приглашений в календарь. Чтобы не получить сообщение, подобное приведенному ниже, вам необходимо убедиться, что organizer адрес электронной почты совпадает с адресом электронной почты from адрес. Это невозможно, если вы используете тестовую среду mailgun.

не поддерживается сообщение календаря

Другие вопросы по тегам