Sending Smart Invites
Required plan: EmergingIn order to have the invite understood correctly by the receiving mail server/client there are a couple of approaches to attaching them required. This ensures that, where supported, the user will also be presented with the Accept/Decline helpers in their email client.
For more detailed best practices, we recommend following the iMIP Best Practices for sending invites. This will guarantee the widest support.
# Using Rails
class SmartInviteMailer < ActionMailer::Base
def invite(smart_invite)
event_ics = smart_invite.attachments.icalendar
method = 'REQUEST' # method=CANCEL in the case of cancellations
attachments.inline["invite.ics"] = {
content_type: "text/calendar; charset=UTF-8; method=#{method}",
encoding: '7bit',
content: event_ics,
}
attachments["invite.ics"] = {
content_type: "application/ics; charset=UTF-8; method=#{method}",
encoding: 'base64',
content: Base64.encode64(event_ics),
}
invite_mail = mail(
to: smart_invite.recipient.email,
subject: "Smart Invite Example",
body: "Here is your invite."
)
# In Rails >= 6, we need to change ActionMailers default inline attachment content-type
# to match the iMIP best practices for sending calendar invites, so that Outlook can show
# the Accept/Tentative/Decline buttons in line.
invite_mail
.parts
.select { |part| contains_calendar_subpart?(part) }
.each { |part| replace_multipart_type(part) }
end
private def contains_calendar_subpart?(part)
part.parts.any? { |subpart| subpart.content_type.start_with? "text/calendar" }
end
private def replace_multipart_type(part)
new_content_type = part.content_type.sub(%r{multipart/[\w]+}, "multipart/alternative")
part.content_type = new_content_type
part
end
end
// Using the https://github.com/PHPMailer/PHPMailer script
require '../vendor/autoload.php';
$mail = new PHPMailer();
$mail->setFrom('application@example.com');
$mail->addAddress($invite->recipient->email);
$mail->Subject = 'Smart Invite Example';
$mail->Body = 'Here is your invite';
$ics = $invite->attachments->icalendar;
$method = 'REQUEST' // method=CANCEL in the case of cancellations
$mail->addAttachment($ics, 'invite.ics', '7bit', "text/calendar; charset=UTF-8; method=$method", 'inline');
$mail->addAttachment(base64_encode($ics), 'invite.ics', 'base64', "application/ics; charset=UTF-8; method=$method", 'attachment');
$mail->send();
// Using the https://nodemailer.com/about/ library
const nodemailer = require('../lib/nodemailer');
// TODO configure transport as required
let transporter = nodemailer.createTransport({});
let ics = invite.attachments.icalendar;
let method = 'REQUEST'; // method=CANCEL in the case of cancellations
let message = {
to: invite.recipient.email,
subject: 'Smart Invite Example',
text: 'Here is your invite',
attachments: [
{
filename: 'invite.ics',
content: ics,
contentType: `text/calendar; charset=UTF-8; method=${method}`,
contentDisposition: 'inline'
},
{
filename: 'invite.ics',
content: Buffer.from(ics, 'base64'),
contentType: `application/ics; charset=UTF-8; method=${method}`,
encoding: 'base64'
},
]
};
transporter.sendMail(message, (error, info) => {
transporter.close();
});
var message = new MailMessage("application@example.com", invite.Recipient.Email);
message.Subject = "Smart Invite Example";
message.Body = "Here is your invite";
var ics = invite.Attachments.ICalendar;
var method = "REQUEST"; // method=CANCEL in the case of cancellations
var inlineAttachment = new Attachment(
new MemoryStream(Encoding.UTF8.GetBytes(ics)),
"invite.ics",
$"text/calendar; charset=UTF-8; method={method}"
);
inlineAttachment.ContentDisposition.Inline = true;
var attachment = new Attachment(
new MemoryStream(Encoding.UTF8.GetBytes(ics)),
"invite.ics",
$"application/ics; charset=UTF-8; method={method}"
);
message.Attachments.Add(inlineAttachment);
message.Attachments.Add(attachment);