Sending Smart Invites
Required plan: EmergingThe majority of email clients will automatically add calendar invites to a user’s calendar if you follow these instructions. This will also mean that, where supported, the user will be presented with the Accept/Decline helpers in their email client.
The two key things to do are:
- Format the ICS correctly.
- Attach the ICS to the email in the correct ways.
Of course, Smart invites created through the Cronofy Smart Invite API Endpoint will be in the correct format. When it comes to attaching the ICS file to the email that’s something your app will need to handle.
We’ve provided some sample code to show how the attachments should be added below. In short you need to attach the file twice. Once inline with 7bit encoding, the other as a standard attachment but with Base64 encoding.
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);