Reputation: 33
I am using PHPMailer to send emails with iCal attachments via office365.
The emails have an attachment named calendar.ics. These attachment are shown by all email clients. BUT neither Outlook nor Thunderbird recognize the iCal format. I have to open the attachment manually to import the appointment into my calendar.
When I send an appointment via Outlook and open this email with Outlook or Thunderbird I can accept the appointment with a simpe click with my mouse. No need to open the attachment. Why are these buttons missing within my emails?
The format of the iCals is valid.
I write the data for the appointment into a string and use $mail->AddStringAttachment("calendar.ics","base64","text\calendar");
Instead of text\calendar I tried application\ics too - with the same result.
What am I doing wrong?
Thx
Upvotes: 0
Views: 269
Reputation: 81
This has been solved.
Create the ical file using something like https://kigkonsult.se/iCalcreator/ as recommended in the documentation. Then attach the file as follows:
$path= 'C:\PHPTemp\invitation.ics';
$name = basename($path);
$encoding = PHPMailer::ENCODING_BASE64;
$type = 'text/calendar; method=REQUEST';
$disposition = 'attachment';
$mail->addAttachment($path, $name, $encoding, $type, $disposition);
The addition of method=REQUEST to the attachment Content-Type tells Microsoft Outlook that the attached event is awaiting a response so it then adds the RSVP buttons to the interface.
For more detail on this have a look at When I add "METHOD: REQUEST" to iCalendar, Gmail stops recognizing as event
I also updated the issue on Github.
Upvotes: 0
Reputation: 33
I finally got these fu.... RSVP-buttons.
Here my code:
$eol = "\r\n";
$vcal = "BEGIN:VCALENDAR$eol";
$vcal .= "PRODID:-//company.de//Irgendein Kalender//EN$eol";
$vcal .= "VERSION:2.0$eol";
$vcal .= "METHOD:" . $method . $eol; // request or cancel
$vcal .= "X-MS-OLK-FORCEINSPECTOROPEN:TRUE$eol";
$vcal .= "X-WR-RELCALID:" . $daten["id"] . $eol;
$vcal .= "BEGIN:VEVENT$eol";
$vcal .= "CLASS:PUBLIC$eol";
$vcal .= "ATTENDEE;RSVP=TRUE;CN=\"Irgendein Termin\";X-NUM-GUESTS=0:MAILTO:" . SMTP_USER . $eol;
$vcal .= "DESCRIPTION:" . $daten["kommentar"] . $eol;
$vcal .= "DTEND:" . $dtend . $eol;
$vcal .= "DTSTAMP:" . $dtstamp . $eol;
$vcal .= "DTSTART:" . $dtstart . $eol;
$vcal .= "LAST-MODIFIED:".date('Ymd').'T'.date('His') . $eol;
$vcal .= "PRIORITY:5$eol";
$vcal .= "SEQUENCE:" . $sequence . $eol;
$vcal .= "SUMMARY:" . $daten["text"] . $eol;
$vcal .= "UID:" . $daten["id"] . $eol;
$vcal .= "X-MICROSOFT-CDO-BUSYSTATUS:BUSY$eol";
$vcal .= "X-MICROSOFT-CDO-IMPORTANCE:1$eol";
$vcal .= "X-MICROSOFT-DISALLOW-COUNTER:FALSE$eol";
$vcal .= "X-MS-OLK-CONFTYPE:0$eol";
$vcal .= "X-GWSHOW-AS:BUSY$eol";
//$vcal .= "X-GWITEM-TYPE:APPOINTMENT\r\n";
if (DEBUGMAIL) {
$vcal .= "ORGANIZER;CN=\"Irgendein Termine\";SENT-BY=”MAILTO:[email protected]”:MAILTO:[email protected]$eol";
} else {
$vcal .= "ORGANIZER;CN=\"Irgendein Termine\":MAILTO:" . SMTP_USER . $eol;
}
$vcal .= "X-GWMESSAGEID:" . $daten["id"] . $eol;
$vcal .= "X-GWRECORDID:" . $daten["id"] . $eol;
$vcal .= "LOCATION:" . $daten["einsatzort"] . $eol;
if($cancel) $vcal .= "STATUS:CANCELLED$eol";
$vcal .= "TRANSP:OPAQUE$eol";
$vcal .= "END:VEVENT$eol";
$vcal .= "END:VCALENDAR$eol";
//Set who the message is to be sent to
if (DEBUGMAIL) {
$mail->addAddress('[email protected]', 'Some Name');
} else {
$mail->addAddress($daten["email"], '');
}
//Set the subject line
$mail->Subject = $mailsubject;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->CharSet = \PHPMailer\PHPMailer\PHPMailer::CHARSET_UTF8;
$mail->Body = "Ein neuer Termin aus Kalender<br>" . $vcal;
$mail->AltBody = "Ein neuer Termin aus Kalender<br>" . $vcal;
//Replace the plain text body with one created manually
$mail->Ical = $vcal;
$mail->AddStringAttachment($vcal, "easytec.ics", "base64", "text/calendar"); //;charset=utf8;method=$method
Hoping this helps others to solve this never ending story - ten years!?
Ah, by the way: the ATTENDEE solved my problem with the $mail->Ical = $vcal;
Good luck Oliver
Upvotes: 1
Reputation: 37700
You might want to read this thread on exactly this subject. This issue has been open for 10 years, and there is still no reliable solution.
The problem is that you've assumed that clients will handle iCal data in the way the standards say they should. It's all very well having validated iCal content, but if the client doesn't implement it properly, you're stuck.
In that thread you can see that there are two basic ways of doing it: iCal data as part of a multipart/alternative
, coupled with text/plain
and text/html
parts; the other is to have an iCal attachment in a multipart/mixed
or other structure. I would prefer the former, however, gmail and Outlook are both horribly inconsistent, so the only vaguely workable approach is to implement both - a multiple/alternative with an attachment, so the iCal data is included twice.
So while your attachment will work for some clients, it won't in others. PHPMailer has built-in iCal support, so you should do it like this (note your call to addStringAttachment
was missing the iCal content param and you had the slash the wrong way around in your MIME type; I suspect this was due to editing for SO rather than your real code):
$mail->Ical = $ical_content;
$mail->addStringAttachment($ical_content, 'ical.ics', 'base64', 'text/calendar');
The final example in the thread (which claims to work in Outlook) actually shows it including iCal data three times, putting a third copy of iCal data as the message body as well. Nuts!
Yes, it's a horrible mess; blame Microsoft and google for not sticking to standards.
Upvotes: 0