1

I am trying to auto-generate calendar invites and send them via SMTP through AWS Simple Email Service (SES). The sending is done via PHPMailer and seems to work with other SMTP servers (unverified), but not with AWS.

It seems that when sending via SES it triggers Amazon to adjust the content headers. No idea how to proceed, appreciate any help as I have to use Amazon as the sending address.

Thank you

Error:

SMTP ERROR: DATA END command failed: 554 Transaction failed: Duplicate header 'Content-Type'.

Code:

// PHPMailer Parameters
$cal_mail = new PHPMailer(true);
//$mail->isSMTP();                                                    // Send using SMTP
$cal_mail->SMTPDebug  = 1;                                              // Enable verbose debug output
$cal_mail->SMTPAuth   = $smtp_auth;                                     // Enable SMTP authentication
$cal_mail->SMTPSecure = 'tls';
$cal_mail->Host       = $smtp_host;                                     // Set the SMTP server to send through
$cal_mail->Port       = $smtp_port;
$cal_mail->SMTPKeepAlive = true;
$cal_mail->Mailer = "smtp";
$cal_mail->Username   = $smtp_username;                                 // SMTP username
$cal_mail->Password   = $smtp_password;                                 // SMTP password
$cal_mail->AddAddress($to_email, $name);                                // Add a recipient
$cal_mail->SetFrom($from_email, $from_name);
$cal_mail->AddReplyTo($to_email, $to_name);


$cal_mail->isHTML(false);                                               // calendar must be FALSE
$cal_mail->ContentType = 'text/calendar';
$cal_mail->Subject = "Outlook Event";
$cal_mail->addCustomHeader('MIME-version', "1.0");
$cal_mail->addCustomHeader('Content-type', "text/calendar; method=REQUEST; charset=UTF-8");
$cal_mail->addCustomHeader('Content-Transfer-Encoding', "7bit");
$cal_mail->addCustomHeader('X-Mailer', "Microsoft Office Outlook 12.0");
$cal_mail->addCustomHeader("Content-class: urn:content-classes:calendarmessage");

// Create Calendar Body
$ical = "BEGIN:VCALENDAR\r\n";
$ical .= "VERSION:2.0\r\n";
$ical .= "PRODID:-//BPNSolutions//SalesDept//EN\r\n";
$ical .= "METHOD:REQUEST\r\n";
$ical .= "BEGIN:VEVENT\r\n";
$ical .= "ORGANIZER;SENT-BY=\"MAILTO:noreply@mail.com\":MAILTO:noreply@mail.com\r\n";
$ical .= "ATTENDEE;CN=" . $to_email . ";ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE:MAILTO:" . $to_email . "\r\n";
$ical .= "UID:" . strtoupper(md5($event_id)) . "-bpn-solutions.com\r\n";
$ical .= "SEQUENCE:" . $sequence . "\r\n";
$ical .= "STATUS:" . $status . "\r\n";
$ical .= "DTSTAMP;TZID=Etc/UTC:" . date('Ymd') . 'T' . date('His') . "\r\n";
$ical .= "DTSTART:" . $start . "T" . $start_time . "\r\n";
$ical .= "DTEND:" . $end . "T" . $end_time . "\r\n";
$ical .= "LOCATION:" . $venue . "\r\n";
$ical .= "SUMMARY:" . $summary . "\r\n";
$ical .= "DESCRIPTION:" . $event['description'] . "\r\n";
$ical .= "BEGIN:VALARM\r\n";
$ical .= "TRIGGER:-PT15M\r\n";
$ical .= "ACTION:DISPLAY\r\n";
$ical .= "DESCRIPTION:Reminder\r\n";
$ical .= "END:VALARM\r\n";
$ical .= "END:VEVENT\r\n";
$ical .= "END:VCALENDAR\r\n";

EDIT 1: the below code successfully generates an email with a .ics attachment, but MS Outlook for desktop is unable to open / read the attachment, respectively does not trigger any accept/refuse buttons when previewing the email. The same attachment does work perfectly fine on Outlook / Apple Mail for iOS though.

// Create Calendar Body
$ical = "BEGIN:VCALENDAR\r\n";
$ical .= "VERSION:2.0\r\n";
$ical .= "PRODID:-//Company//SalesDept//EN\r\n";
$ical .= "METHOD:REQUEST\r\n";
$ical .= "NAME: Test1\r\n";
$ical .= "X-WR-CALNAME:Test Calendar\r\n";
$ical .= "BEGIN:VEVENT\r\n";
$ical .= "ORGANIZER;CN=\"Company Name:mailto:noreply@domain.com\r\n";
$ical .= "ATTENDEE;CN=" . $to_email . ";ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE:MAILTO:" . $to_email . "\r\n";
$ical .= "UID:" . md5(uniqid(mt_rand(), true)) . "domain.com\r\n";
$ical .= "SEQUENCE:" . $sequence . "\r\n";
$ical .= "STATUS:" . $status . "\r\n";
$ical .= "DTSTART:" . $start . "T" . $start_time . "Z\r\n";
$ical .= "DTEND:" . $end . "T" . $end_time . "Z\r\n";
$ical .= "DTSTAMP:" . date('Ymd') . 'T' . date('His') . "Z\r\n";
$ical .= "LOCATION:" . $venue . "\r\n";
$ical .= "SUMMARY:" . $summary . "\r\n";
$ical .= "DESCRIPTION:Some descriptive text here.\r\n";
$ical .= "BEGIN:VALARM\r\n";
$ical .= "TRIGGER:-PT15M\r\n";
$ical .= "ACTION:DISPLAY\r\n";
$ical .= "DESCRIPTION:Reminder\r\n";
$ical .= "END:VALARM\r\n";
$ical .= "END:VEVENT\r\n";
$ical .= "END:VCALENDAR\r\n";

$cal_mail->ContentType = 'text/calendar';
$cal_mail->Subject = $summary;
$cal_mail->Body = "This is the body text which is meant to be shown in the email body";
$cal_mail->AltBody = $ical;
$cal_mail->Ical = $ical;
Armitage2k
  • 1,164
  • 2
  • 27
  • 59

2 Answers2

0

Stop right there. You're trying to undermine all the things that PHPMailer does for you. If you're going to try to build your own messages from scratch, you don't need PHPMailer. PHPMailer has built-in support for sending iCal attachments and message parts, so remove all those addCustomHeader calls. Sending a message that contains only an ical part is very unlikely to work universally (there has been a lot of discussion related to the problems in various ical clients – short version: both gmail and outlook are absolutely terrible at it) so set a message body, and then add your iCal part after creating your $ical string:

$cal_mail->Body = 'Here is your calendar invitation';
$cal_mail->Ical = $ical;

And that's all there is to it. All the headers and encoding are taken care of for you.

To debug, you really want to have SMTPDebug = 2; 1 is not very useful. Also don't set Mailer directly; call isSMTP() instead.

Synchro
  • 35,538
  • 15
  • 81
  • 104
  • thanks for that. The invite and .ics attachment now generates, but outlook cannot open the invite. Google references compatibility issues, any recommendations on that? thanks – Armitage2k Nov 06 '20 at 22:27
  • Outlook is *very* fussy about iCal formats. I would recommend testing using iCal content generated by outlook before trying to make your own. – Synchro Nov 07 '20 at 08:12
  • the above `$ical` does not trigger the accept/refuse buttons in Outlook for desktop, but do work perfectly fine on iOS. But when looking into the source of an outlook cal invite, I see no calendar details at all...? – Armitage2k Nov 07 '20 at 14:05
  • So you see what I mean about it being fussy! I have essentially given up on it as I think it’s not possible to make it work in all of outlook, gmail, and iOS at the same time. So long as the ics attachment is visible, it’s usable in everything. – Synchro Nov 07 '20 at 16:36
  • 1
    have a look at my posted answer below, it works now on desktop for Outlook on MAC and PC, as well as mobile on iOS and Android. – Armitage2k Nov 08 '20 at 00:25
0

After a lot of trial and error and getting it work on either Desktop or Mobile, I finally managed to find the correct combination of $ical elements to have the Accept / Refuse buttons appear on both MS Outlook for Desktop, Outlook for iOS and Apple Mail. Please note that the below does not work with Gmail.

// Create Calendar Body
$ical = "BEGIN:VCALENDAR\r\n";
$ical .= "VERSION:2.0\r\n";
$ical .= "PRODID:-//CompanyName//SalesDept//EN\r\n";
$ical .= "METHOD:REQUEST\r\n";
$ical .= "NAME: Test1\r\n";
$ical .= "X-WR-CALNAME:Test Cal\r\n";
$ical .= "BEGIN:VEVENT\r\n";
$ical .= "ORGANIZER;CN=" . $from_name . ":mailto:" . $from_email . "\r\n";
$ical .= "ATTENDEE;CN=" . $to_email . ";ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE:MAILTO:" . $to_email . "\r\n";
$ical .= "UID:" . md5(uniqid(mt_rand(), true)) . "mydomain.com\r\n";
$ical .= "SEQUENCE:" . $sequence . "\r\n";
$ical .= "STATUS:" . $status . "\r\n";
$ical .= "DTSTART:" . $start . "T" . $start_time . "Z\r\n";
$ical .= "DTEND:" . $end . "T" . $end_time . "Z\r\n";
$ical .= "DTSTAMP:" . date('Ymd') . 'T' . date('His') . "Z\r\n";
$ical .= "LOCATION:" . $venue . "\r\n";
$ical .= "SUMMARY:" . $summary . "\r\n";
$ical .= "DESCRIPTION:Some descriptive text here.\r\n";
$ical .= "BEGIN:VALARM\r\n";
$ical .= "TRIGGER:-PT15M\r\n";
$ical .= "ACTION:DISPLAY\r\n";
$ical .= "DESCRIPTION:Reminder\r\n";
$ical .= "END:VALARM\r\n";
$ical .= "END:VEVENT\r\n";
$ical .= "END:VCALENDAR\r\n";

$cal_mail->ContentType = 'text/calendar';
$cal_mail->Subject = $summary;
$cal_mail->Body = "This is the body text";
$cal_mail->AltBody = $ical;
$cal_mail->AddStringAttachment("$ical", "attachment.ics", "base64", "text/calendar; charset=utf-8; method=REQUEST");
$cal_mail->Ical = $ical;

It worth pointing out that MS Outlook for Desktop did not properly show the calendar invite until I added below code, attaching the .ics attachment to the mail (even though PHPMailer supposedly does that automatically).

Kudos to Frank Van Der Oort who pinpointed this bit here

Armitage2k
  • 1,164
  • 2
  • 27
  • 59