Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iCalendar invite is not showing RSVP buttons in email clients #175

Open
ghost opened this issue Jan 29, 2014 · 42 comments
Open

iCalendar invite is not showing RSVP buttons in email clients #175

ghost opened this issue Jan 29, 2014 · 42 comments

Comments

@ghost
Copy link

ghost commented Jan 29, 2014

I'm using PHPMailer to send email. My ics content is:

BEGIN:VCALENDAR
METHOD:REQUEST
VERSION:2.0
PRODID:-//FooBar//FooBar Calendar//EN
BEGIN:VEVENT
UID:8f5a0777-bf6d-17d2-f14a-52e7feedf810
ORGANIZER;CN=Foo:foo@bar.com
DTSTART:20140130T191500Z
DTEND:20140130T194500Z
DTSTAMP:20140129T144300Z
SUMMARY:Foo Bar 11
DESCRIPTION:
END:VEVENT
END:VCALENDAR

For some reason I don't see the expected RSVP buttons in any email clients. Both Gmail and Mac Mail simply include the ics as a file attachment, I assume as a fallback. So there must be something wrong. I have not tried Outlook, but I don't see any reason why it would be different in a third client. The contents of an email being sent are below. Can you see anything that looks incorrect? Thank you.

Return-Path: REDACTED
Received: REDACTED
Date: Wed, 29 Jan 2014 09:43:18 -0500
Return-Path: REDACTED
To: REDACTED
From: REDACTED
Reply-To: REDACTED
Subject: Meeting - Foo Bar 11
Message-ID: <7004961cd9df04181047296f98260834@localhost>
X-Priority: 3
X-Mailer: PHPMailer 5.2.7 (https://github.com/PHPMailer/PHPMailer/)
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="b1_7004961cd9df04181047296f98260834"
Content-Transfer-Encoding: base64

--b1_7004961cd9df04181047296f98260834
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64

VG86IEZvbyBCYXINCg0KDQpBZG1pbmlzdHJhdG9yIGhhcyBpbnZpdGVkIHlvdSB0byBhIE1lZXRpbmcNCg0KDQpTdWJqZWN0OiBGb28gQmFyIDExDQoNClN0YXJ0IERhdGU6IDAxLzMwLzIwMTQgMDI6MTVwbSBFU1QoLTA1OjAwKQ0KDQpFbmQgRGF0ZTogMDEvMzAvMjAxNCAwMjo0NXBtIEVTVCgtMDU6MDApDQoNCg0KRGVzY3JpcHRpb246IA0KDQoNCkFjY2VwdCB0aGlzIG1lZXRpbmc6DQoNCmh0dHA6Ly9sb2NhbGhvc3Q6ODg4OC9pbmRleC5waHA/ZW50cnlQb2ludD1hY2NlcHREZWNsaW5lJm1vZHVsZT1NZWV0aW5ncyZ1c2VyX2lkPTEmcmVjb3JkPThmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMCZhY2NlcHRfc3RhdHVzPWFjY2VwdA0KDQoNClRlbnRhdGl2ZWx5IEFjY2VwdCB0aGlzIG1lZXRpbmcNCg0KaHR0cDovL2xvY2FsaG9zdDo4ODg4L2luZGV4LnBocD9lbnRyeVBvaW50PWFjY2VwdERlY2xpbmUmbW9kdWxlPU1lZXRpbmdzJnVzZXJfaWQ9MSZyZWNvcmQ9OGY1YTA3NzctYmY2ZC0xN2QyLWYxNGEtNTJlN2ZlZWRmODEwJmFjY2VwdF9zdGF0dXM9dGVudGF0aXZlDQoNCg0KRGVjbGluZSB0aGlzIG1lZXRpbmcNCg0KaHR0cDovL2xvY2FsaG9zdDo4ODg4L2luZGV4LnBocD9lbnRyeVBvaW50PWFjY2VwdERlY2xpbmUmbW9kdWxlPU1lZXRpbmdzJnVzZXJfaWQ9MSZyZWNvcmQ9OGY1YTA3NzctYmY2ZC0xN2QyLWYxNGEtNTJlN2ZlZWRmODEwJmFjY2VwdF9zdGF0dXM9ZGVjbGluZQ0KDQo=


--b1_7004961cd9df04181047296f98260834
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: base64

PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTCAxLjAgVHJhbnNpdGlvbmFsLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL1RSL3hodG1sMS9EVEQveGh0bWwxLXRyYW5zaXRpb25hbC5kdGQiPg0KPGh0bWwgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIGxhbmc9J2VuX3VzJz4NCjxoZWFkPg0KPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9VVRGLTgiIC8+DQo8dGl0bGU+DQpNZWV0aW5nIC0gRm9vIEJhciAxMQ0KPC90aXRsZT4NCjwvaGVhZD4NCjxib2R5Pg0KVG86IEFkbWluaXN0cmF0b3I8YnIgLz48YnIgLz4NCkFkbWluaXN0cmF0b3IgaGFzIGludml0ZWQgeW91IHRvIGEgTWVldGluZzxiciAvPjxiciAvPg0KU3ViamVjdDogRm9vIEJhciAxMTxiciAvPg0KU3RhcnQgRGF0ZTogMDEvMzAvMjAxNCAwMjoxNXBtIEVTVCgtMDU6MDApPGJyIC8+DQpFbmQgRGF0ZTogMDEvMzAvMjAxNCAwMjo0NXBtIEVTVCgtMDU6MDApPGJyIC8+DQoNCkRlc2NyaXB0aW9uOiA8YnIgLz48YnIgLz4NCkFjY2VwdCB0aGlzIG1lZXRpbmc6PGJyIC8+DQo8YSBocmVmPSJodHRwOi8vbG9jYWxob3N0Ojg4ODgvaW5kZXgucGhwP2VudHJ5UG9pbnQ9YWNjZXB0RGVjbGluZSZtb2R1bGU9TWVldGluZ3MmdXNlcl9pZD0xJnJlY29yZD04ZjVhMDc3Ny1iZjZkLTE3ZDItZjE0YS01MmU3ZmVlZGY4MTAmYWNjZXB0X3N0YXR1cz1hY2NlcHQiPmh0dHA6Ly9sb2NhbGhvc3Q6ODg4OC9pbmRleC5waHA/ZW50cnlQb2ludD1hY2NlcHREZWNsaW5lJm1vZHVsZT1NZWV0aW5ncyZ1c2VyX2lkPTEmcmVjb3JkPThmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMCZhY2NlcHRfc3RhdHVzPWFjY2VwdDwvYT48YnIgLz48YnIgLz4NClRlbnRhdGl2ZWx5IEFjY2VwdCB0aGlzIG1lZXRpbmc8YnIgLz4NCjxhIGhyZWY9Imh0dHA6Ly9sb2NhbGhvc3Q6ODg4OC9pbmRleC5waHA/ZW50cnlQb2ludD1hY2NlcHREZWNsaW5lJm1vZHVsZT1NZWV0aW5ncyZ1c2VyX2lkPTEmcmVjb3JkPThmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMCZhY2NlcHRfc3RhdHVzPXRlbnRhdGl2ZSI+aHR0cDovL2xvY2FsaG9zdDo4ODg4L2luZGV4LnBocD9lbnRyeVBvaW50PWFjY2VwdERlY2xpbmUmbW9kdWxlPU1lZXRpbmdzJnVzZXJfaWQ9MSZyZWNvcmQ9OGY1YTA3NzctYmY2ZC0xN2QyLWYxNGEtNTJlN2ZlZWRmODEwJmFjY2VwdF9zdGF0dXM9dGVudGF0aXZlPC9hPjxiciAvPjxiciAvPg0KRGVjbGluZSB0aGlzIG1lZXRpbmc8YnIgLz4NCjxhIGhyZWY9Imh0dHA6Ly9sb2NhbGhvc3Q6ODg4OC9pbmRleC5waHA/ZW50cnlQb2ludD1hY2NlcHREZWNsaW5lJm1vZHVsZT1NZWV0aW5ncyZ1c2VyX2lkPTEmcmVjb3JkPThmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMCZhY2NlcHRfc3RhdHVzPWRlY2xpbmUiPmh0dHA6Ly9sb2NhbGhvc3Q6ODg4OC9pbmRleC5waHA/ZW50cnlQb2ludD1hY2NlcHREZWNsaW5lJm1vZHVsZT1NZWV0aW5ncyZ1c2VyX2lkPTEmcmVjb3JkPThmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMCZhY2NlcHRfc3RhdHVzPWRlY2xpbmU8L2E+PGJyIC8+PGJyIC8+DQo8L2JvZHk+DQo8L2h0bWw+


--b1_7004961cd9df04181047296f98260834
Content-Type: text/calendar; method=REQUEST; charset=UTF-8
Content-Transfer-Encoding: base64

QkVHSU46VkNBTEVOREFSDQpNRVRIT0Q6UkVRVUVTVA0KVkVSU0lPTjoyLjANClBST0RJRDotLy9Gb29CYXIvL0Zvb0JhciBDYWxlbmRhci8vRU4NCkJFR0lOOlZFVkVOVA0KVUlEOjhmNWEwNzc3LWJmNmQtMTdkMi1mMTRhLTUyZTdmZWVkZjgxMA0KT1JHQU5JWkVSO0NOPUZvbzpmb29AYmFyLmNvbQ0KRFRTVEFSVDoyMDE0MDEzMFQxOTE1MDBaDQpEVEVORDoyMDE0MDEzMFQxOTQ1MDBaDQpEVFNUQU1QOjIwMTQwMTI5VDE0NDMwMFoNClNVTU1BUlk6Rm9vIEJhciAxMQ0KREVTQ1JJUFRJT046DQpFTkQ6VkVWRU5UDQpFTkQ6VkNBTEVOREFSDQo=



--b1_7004961cd9df04181047296f98260834--

P.S. Sorry about it being base64 encoded. I wanted to show a true representation of the email instead of changing it any way that may skew the results. I just use http://www.base64decode.org/ to decode the contents.

P.P.S. The base64 contents show as one string, but the email is sent with a max of 1000 characters per line. I just needed to remove some sensitive information, so I had to re-encode those parts, which removed the breaks.

@Synchro
Copy link
Member

Synchro commented Jan 29, 2014

The attachment is all that the iCal/ICS format defines. In google calendar invitations their MIME structure is exactly the same in PHPMailer, but the HTML message body contains links back to google calendar that fulfil the yes/no/maybe functions. PHPMailer doesn't know anything about the system the calendar relates to, so it's up to you to provide that functionality. If individual email clients have support for ics attachment types (I've not seen mail do this, but then I've only every received invitations from gcal) then it could possibly do something with it.

I've found some references (on stack overflow) to exactly what things like Outlook are looking for and I've been trying them out in a local version but I've not managed to make anything special happen. I also found an ICS validator that highlighted a few problems with the bundled ICS generator class.

I've realised that there isn't a code example for using calendar events, but there is a test case that's easily adapted.

@ghost
Copy link
Author

ghost commented Jan 31, 2014

Thanks for the response. I got things sorted out. I was missing mailto: in the ORGANIZER property value. It should have been ORGANIZER;CN=Foo:mailto:foo@bar.com. And the biggest thing was that I needed to force the use of CRLF for line endings. The ATTENDEE property is also required, but that didn't seem to be a requirement to get Outlook and Mac Mail to render the RSVP buttons. My final iCal metadata looked like:

VERSION:2.0
BEGIN:VCALENDAR
PRODID:-//FooBar//FooBar Calendar//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:8f5a0777-bf6d-17d2-f14a-52e7feedf810
ORGANIZER;CN=Foo:mailto:foo@bar.com
DTSTART:20140130T191500Z
DTEND:20140130T194500Z
DTSTAMP:20140129T144300Z
SUMMARY:Foo Bar
DESCRIPTION:
END:VEVENT
END:VCALENDAR

For my situation, I was unable to use the bundled EasyPeasyICS, but I did look at the iCal unit test to see how to set things up. And I probably used the same validators as you. The validators don't seem to catch everything though; the line endings are an example of something they missed. And as you mentioned, EasyPeasyICS doesn't seem match up with RFC 5546. As ICS support is expanded, it might be worth considering replacing EasyPeasyICS with something that implements the spec.

Some other things of interest that I learned through this exercise:

  • Outlook and Mac Mail only show their RSVP buttons if you add the ICS content in the way that PHPMailer has implemented it. They will not show RSVP buttons if the ICS file is simply attached.
  • Gmail only shows its "Add to calendar" wrapper (its equivalent to RSVP buttons) if the ICS file is attached. The event is only added to your Google Calendar if the ICS file is attached.
  • When sending an invite from Outlook, the ICS content is added the way PHPMailer has implemented it. Thus, Outlook and Mac Mail will recognize it but Gmail will not.
  • When sending an invite from Mac Mail/iCal, the ICS file is attached. Thus, Gmail will recognize it but Outlook and Mac Mail will not.
  • When sending an invite from Gmail/Google Calendar, the ICS file is attached AND the ICS content is added the way PHPMailer has implemented it. Thus, all three clients will recognize it.

@Synchro
Copy link
Member

Synchro commented Jan 31, 2014

That's some great research, thanks for the effort! I've had emails with the author of EasyPeasyICS and he's happy for me to take it over, so we're free to do whatever we want with it.

PHPMailer should be defaulting to CRLF line breaks; I don't think it should allow you to switch since none of the RFCs allow it. Attaching both formats seems sensible.

In my experiments I needed to alter various things in PHPMailer, in particular I needed to be able to provide a content-disposition header for the ICS part (from what I read, some clients require it to be marked as 'inline') and that required extending the getBoundary method.

I'll push my changes to my own fork later, see what you think. It would be good if you could wrap up your changes in a pull request.

@ghost
Copy link
Author

ghost commented Jan 31, 2014

As far as the line endings go, the issue is with the ICS metadata. Since EasyPeasyICS is just wrapping a long string in EasyPeasyICS::render() the line endings are at the mercy of the OS on which the application is running (or whatever PHP_EOL is). If your system uses \n, then those bytes will be encoded by PHPMailer. If your encoding is base64 then those lines are not fixed by PHPMailer::fixEOL. Only the lines at the end of each chunk would be fixed. That's just one detail to pay attention to.

I didn't do any patching of PHPMailer or EasyPeasyICS -- I only made modifications in my own code that was building the ICS content to avoid changing a third-party library -- but I can certainly whip up a PR to address some of the things I learned. Is the plan to put EasyPeasyICS in its own repo and make it a dependency or to just start changing it from within the PHPMailer repo? I read some of your comments about using dependency injection for the SMTP class to allow for custom implementations, so this could be another example of the same concern.

I did attempt a patch of PHPMailer for adding both the attachment and the ICS message part. However, I never got it to work in Gmail and I had to give up for the time being. So it would be premature for me to try to open a PR for that. But I'll share the patch I have, as well as the email sources from PHPMailer and Gmail that I've been diff-ing to help me chase down the root cause. Maybe one of us, or someone else in the community, will be able to figure it out from there.

@Bladezal
Copy link

Hello, i've a problem sending ical through PHPMailer to a gmail account, the ical file is send as an attachment, and for some reazon gmail don't add it to the calendar, if the same file is sent to an account and opened with Outlook, there is no problem at all.
Could you help me with this matter?

Here is an example of the ical file created with icalcreator:

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Skytel.com//NONSGML kigkonsult.se iCalcreator 2.20.2//
CALSCALE:GREGORIAN
METHOD:REQUEST
X-WR-CALNAME:Entrevista
X-WR-CALDESC:Entrevista con postulante para Programador
BEGIN:VEVENT
UID:20140522T123044PYT-5113wIaZ2j@Skytel.com
DTSTAMP:20140522T163044Z
ATTENDEE;RSVP=TRUE;CN= EVERTON DANIEL CAZAL KONTOVSKI;X-NUM-GUESTS=0:MAILTO
 :daniel.cazal@skytel.com.py
DESCRIPTION:El día 23/05/2014 a las 16:30 hs  tiene entrevista con  la seño
 ra Alicia Romina García Olmedo por la postulación al puesto de Programador
 .\n
DTSTART:20140523T163000
DURATION:PT0H30M0S
LOCATION:Sala de Reuniones
ORGANIZER;CN= EVERTON DANIEL CAZAL KONTOVSKI:MAILTO:daniel.cazal@skytel.com
 .py
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Entrevista con postulante para Programador
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

Many thanks for any help you could bringme.

@Synchro
Copy link
Member

Synchro commented May 27, 2014

If you read the rest of this thread, you'll see the problem is that the ICS file needs to be added both as an attachment and as a member of a multipart/alternative MIME structure to satisfy both gmail and outlook. The problem in PHPMailer is that we're heading for an exponential explosion in the number of possible combinations of MIME structures, and because PHPMailer only has preset options, it's getting out of hand.
I did start having a look at this, but it's just really difficult to handle it in a sane way with the current MIME structure, and a complete overhaul of that is beyond the scope of this ticket. Something you could do is build the message with Zend or Pear MIME classes and then just use PHPMailer to send it.

@StrayDawg
Copy link

Is there an example of how to actually send an invite using phpmailer? I'm guessing on the format and order of things
...

    $invite = new EasyPeasyICS();
    $invite->addEvent('06-06-2014 08:00:00','06-06-2014 17:00:00',"TEST","TEST","");
    $mail = new PHPMailer();
    $mail->isSMTP();
    $mail->IsHTML(false);
    $mail->SMTPDebug = 2;
    $mail->Debugoutput = 'html';    
    $mail->Host = 'spo.test.com';
    $mail->Port = 587;
    $mail->SMTPSecure = 'tls';
    $mail->setFrom('david.g.obrien@test.com', 'OBrien, David');
    $mail->addAddress('david.g.obrien@test.com', 'OBrien, David');    
    $mail->Subject = "TEST CALENDAR";
    $mail->Body = $invite; 
    $mail->AltBody = "TEST CALENDAR";
    $mail->Ical = $invite;
    if (!$mail->send()) {
        echo "Mailer Error: " . $mail->ErrorInfo;
    } else {
        echo "Message sent!";
    }

...

@Synchro
Copy link
Member

Synchro commented May 29, 2014

PHPMailer expects a string containing the ICS data, so set it like this when using EasyPeasyICS:

$mail->Ical = $invite->render();

@Adrian-Selva
Copy link

Hello, I have the same problem than Bladezal , the RSVP buttons don't appear for me on Gmail however I include the ical in the multipart/alternative and as a attachment as you say and it works only on Outlook. I would appreciate if you could help me with this, here my headers and the Ical:

Content-Type: multipart/mixed;
boundary="b1_48fb71c31b1b47230328819926821af0"
Content-Transfer-Encoding: 8bit
--b1_48fb71c31b1b47230328819926821af0

Content-Type: multipart/alternative;
boundary="b2_48fb71c31b1b47230328819926821af0"
--b2_48fb71c31b1b47230328819926821af0
Content-Type: text/plain; charset=us-ascii
Test

--b2_48fb71c31b1b47230328819926821af0

Content-Type: text/calendar; method=REQUEST; charset=UTF-8
Content-Transfer-Encoding: 8bit
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
METHOD:REQUEST
BEGIN:VEVENT
ORGANIZER;CN='Bob Miller':MAILTO:bmiller34@gmail.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Bob Miller;X-NUM-GUESTS=0:mailto:bmiller34@gmail.com
DTSTART:20141031T170000Z
DTEND:20141031T180000Z
LOCATION: Online Seminar
UID:d1b94cf324fe08271cefda68b295ee99@EasyPeasyICS.php
DTSTAMP:20141031T170000Z
DESCRIPTION:invitation to seminar
SUMMARY:invitation to seminar
SEQUENCE:0
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

--b2_48fb71c31b1b47230328819926821af0

Content-Type: text/html; charset=us-ascii


<title> Seminar invitation </title> This is an invitation to attend a seminar

Host: smtp.gmail.com
Attachments:
  • Name: invite.ics, Encoding: base64, Type: text/calendar

--b2_48fb71c31b1b47230328819926821af0--

--b1_48fb71c31b1b47230328819926821af0

Content-Type: text/calendar; name="invite.ics"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=invite.ics
QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KUFJPRElEOi0vL01pY3Jvc29mdCBDb3Jwb3JhdGlvbi8vT3V0bG9vayAxMS4wIE1JTUVESVIvL0VODQpNRVRIT0Q6UkVRVUVTVA0KQkVHSU46VkVWRU5UDQpPUkdBTklaRVI7Q049J0JvYiBNaWxsZXInOk1BSUxUTzpibWlsbGVyMzRAZ21haWwuY29tDQpBVFRFTkRFRTtDVVRZUEU9SU5ESVZJRFVBTDtST0xFPVJFUS1QQVJUSUNJUEFOVDtQQVJUU1RBVD1ORUVEUy1BQ1RJT047UlNWUD1UUlVFO0NOPUJvYiBNaWxsZXI7WC1OVU0tR1VFU1RTPTA6bWFpbHRvOmFkcmlhbnNlZ2FAZ21haWwuY29tDQpEVFNUQVJUOjIwMTQxMDMxVDE3MDAwMFoNCkRURU5EOjIwMTQxMDMxVDE4MDAwMFoNCkxPQ0FUSU9OOiBPbmxpbmUgU2VtaW5hciANClVJRDoyNjI4NDE3YjliN2YyOWZhZjZhMDc2N2FjZjAxNGZhNkBFYXN5UGVhc3lJQ1MucGhwDQpEVFNUQU1QOjIwMTQxMDMxVDE3MDAwMFoNCkRFU0NSSVBUSU9OOmludml0YXRpb24gdG8gc2VtaW5hcg0KU1VNTUFSWTppbnZpdGF0aW9uIHRvIHNlbWluYXINClNFUVVFTkNFOjANClNUQVRVUzpDT05GSVJNRUQNCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVINCg==

--b1_48fb71c31b1b47230328819926821af0--

@Synchro
Copy link
Member

Synchro commented Oct 31, 2014

If you read back through this thread, you'll see that gmail is broken, and that fixing this in PHPMailer is not in the least bit simple, so it's not going to be fixed soon.

@cm8solutions
Copy link

Hi!

Hopefully someone is still following this topic because I really need help with this RSVP button issue. The thing is that I don't want those buttons to to appear so that the event is automatically accepted (mainly in Outlook). Any ideas how to do that?

@Synchro
Copy link
Member

Synchro commented Nov 3, 2015

If you don't want to give them a choice, why even ask? Just add them to the event without asking.

@cm8solutions
Copy link

But how do I do that? What changes do I have to make?

Thanks a lot!

@Synchro
Copy link
Member

Synchro commented Nov 3, 2015

I've no idea - you'd need to talk to the calendar server directly, not via email.

@kamil-kielczewski
Copy link

kamil-kielczewski commented Feb 21, 2017

For me problem was that RSVP buttons not appear in Gmail although I send valid .ics file. The solution was add proper mime type to email .ics file attachement:

Content-Type: text/calendar; method=REQUEST; charset=UTF-8

I do it in laravel 5 in this way:

    Mail::queue('emails.reservationInvitation', compact('guest','attendeesList','reservation', 'dayBegin', 'dayName', 'hourBegin', 'hourEnd', 'length' )
            , function ($message) use ($reservation, $subject, $guest, $icalendar) {
                $message->attachData($icalendar, "invite.ics", ['mime' => 'text/calendar; method=REQUEST; charset=UTF-8']);
                $message->to($guest['email'])->subject($subject); 
            });

where $icalendar was string with content of my invite.ics file.

Synchro added a commit that referenced this issue Feb 21, 2017
@Synchro
Copy link
Member

Synchro commented Feb 21, 2017

You can specify a MIME type when you add an attachment:

$mail->addAttachment('path/to/calendar.ics', 'calendar.ics', 'base64', 'text/calendar');

If you don't provide a MIME type manually like this, PHPMailer has a built-in list of MIME types that it associates with file extensions automatically, however ics was missing from the list. I've now added it in the 6.0 branch.

Note that when you use PHPMailer's built-in embedded iCal support (via the Ical property mentioned in this thread), it did already set the MIME type correctly.

@christophercarlsson
Copy link

If I add an Ical and attach a file at the same time, the Ical info is not sent with the mail. If I remove the attachment, the mail is sent with the Ical info (however not recognized by Outlook/Mail..).

My PHP
`$fp = fopen($_SERVER['DOCUMENT_ROOT'] . "/ical.ics", "wb");
fwrite($fp, $this->renderIcs($events, false));
fclose($fp);

	$mail = new PHPMailer();
	$mail->CharSet = "UTF-8";
	$mail->isSMTP();
	$mail->IsHTML(false);
	$mail->Host = env('MAIL_HOST');
	$mail->Port = env('MAIL_PORT');
	$mail->SMTPAuth = true;
	$mail->Username = env('MAIL_USERNAME');
	$mail->Password = env('MAIL_PASSWORD');
	$mail->setFrom($email, $name);
	$mail->addAddress($email, $name);
	$mail->Subject = trans('emails.reservation.email_subject', ['reservation_title' => strip_tags($reservation->title)]);
	$mail->Body = "test";
	$mail->AltBody = "test";
	$mail->addAttachment($_SERVER['DOCUMENT_ROOT'] . "/ical.ics", 'calendar.ics', 'base64', 'text/calendar');
	$mail->Ical = $this->renderIcs($events, false);

	$mail->Send();
	}`

Gives me the following mail:

Date: Tue, 1 Aug 2017 14:44:29 +0000
To: xxx
From: xxx
Subject: Calendar Invite: asd
Message-ID: 7401f051c441e65793fba6425f30fccd@laravel
X-Mailer: PHPMailer 5.2.24 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="b1_7401f051c441e65793fba6425f30fccd"
Content-Transfer-Encoding: 8bit

This is a multi-part message in MIME format.

--b1_7401f051c441e65793fba6425f30fccd
Content-Type: multipart/alternative;
boundary="b2_7401f051c441e65793fba6425f30fccd"

--b2_7401f051c441e65793fba6425f30fccd
Content-Type: text/plain; charset=us-ascii

test

--b2_7401f051c441e65793fba6425f30fccd
Content-Type: text/html; charset=us-ascii

test

--b2_7401f051c441e65793fba6425f30fccd--

--b1_7401f051c441e65793fba6425f30fccd
Content-Type: text/calendar; name="calendar.ics"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=calendar.ics

VkVSU0lPTjoyLjANCkJFR0lOOlZDQUxFTkRBUg0KUFJPRElEOi0vL2hhY2tzdy9oYW5kY2FsLy9OT05TR01MIHYxLjAvL0VODQpNRVRIT0Q6UkVRVUVTVA0KQkVHSU46VkVWRU5UDQpVSUQ6eHh4LTEyMy14eHgNCk9SR0FOSVpFUjtDTj14eHg6bWFpbHRvOnh4eA0KRFRTVEFSVDoyMDE3MDgwMVQxMzMwMDBaDQpEVEVORDoyMDE3MDgwMVQxMzQ1MDBaDQpEVFNUQU1QOjIwMTcwODAxVDE0NDQyOVoNClNVTU1BUlk6YXNkDQpERVNDUklQVElPTjp0ZXN0DQpMT0NBVElPTjpUZXN0aW5nIHJlc291cmNlDQpTRVFVRU5DRToxDQpFTkQ6VkVWRU5UDQpFTkQ6VkNBTEVOREFS

--b1_7401f051c441e65793fba6425f30fccd--

However - removing the attached file generates this:

Date: Tue, 1 Aug 2017 14:44:17 +0000
To: xxx
From: xxx
Subject: Calendar Invite: asd
Message-ID: 0665272647344ea75df23a6698e8a8ff@laravel
X-Mailer: PHPMailer 5.2.24 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="b1_0665272647344ea75df23a6698e8a8ff"
Content-Transfer-Encoding: 8bit

This is a multi-part message in MIME format.

--b1_0665272647344ea75df23a6698e8a8ff
Content-Type: text/plain; charset=us-ascii

test

--b1_0665272647344ea75df23a6698e8a8ff
Content-Type: text/html; charset=us-ascii

test

--b1_0665272647344ea75df23a6698e8a8ff
Content-Type: text/calendar; method=REQUEST; charset=UTF-8
Content-Transfer-Encoding: 8bit

VERSION:2.0
BEGIN:VCALENDAR
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:xxx-123-xxx
ORGANIZER;CN=xxx:mailto:xxx
DTSTART:20170801T131500Z
DTEND:20170801T133000Z
DTSTAMP:20170801T144417Z
SUMMARY:asd
DESCRIPTION:test
LOCATION:Testing resource
SEQUENCE:1
END:VEVENT
END:VCALENDAR

--b1_0665272647344ea75df23a6698e8a8ff--

What is causing this and why is it not working? Seemingly my ics file is valid and according to what i see in this thread..

@Synchro
Copy link
Member

Synchro commented Aug 1, 2017

Thanks for the clear description. This is down to PHPMailer's preset MIME structures - as soon as you add attachments, the message is built using the alt_attach structure, which doesn't have Ical support. I've just pushed a change to the 6.0 branch that does support for that, so you can at least attempt this workaround - please report your results!

@christophercarlsson
Copy link

Thank you, that worked. They both are included now. However - I still get no RSVP buttons in either of Mac Mail and Outlook. Any idea on what is wrong? Im able to click the attached file in Mail and get it to add it to my calendar, but the same can not be done i Outlook.

Date: Tue, 1 Aug 2017 15:42:22 +0000
To: xxx
From: xxx
Subject: Calendar Invite: test
Message-ID: 7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e@laravel
X-Mailer: PHPMailer 6.0.0 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="b1_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e"
Content-Transfer-Encoding: 8bit

This is a multi-part message in MIME format.
--b1_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e
Content-Type: multipart/alternative;
boundary="b2_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e"

--b2_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e
Content-Type: text/plain; charset=us-ascii

test

--b2_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e
Content-Type: text/html; charset=us-ascii

test

--b2_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e
Content-Type: text/calendar; method=REQUEST; charset=UTF-8
Content-Transfer-Encoding: 8bit

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:book-8@getmeetio.com
ORGANIZER;CN=Christopher Carlsson:mailto:xxxx
ATTENDEE;ROLE=REQ-PARTICIPANT;CN=Christopher Carlsson:mailto:xxxx
ACTION;RSVP=TRUE;CN=Christopher Carlsson;X-NUM-GUESTS=0:mailto:xxx
DTSTART:20170802T090000Z
DTEND:20170802T091500Z
DTSTAMP:20170801T154222Z
SUMMARY:test
DESCRIPTION:test
LOCATION:Testing resource
SEQUENCE:1
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

--b2_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e--

--b1_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e
Content-Type: text/calendar; name="calendar.ics"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=calendar.ics

QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KUFJPRElEOi0vL01pY3Jvc29mdCBDb3Jwb3JhdGlvbi8vT3V0bG9vayAxMS4wIE1JTUVESVIvL0VODQpNRVRIT0Q6UkVRVUVTVA0KQkVHSU46VkVWRU5UDQpVSUQ6Ym9vay04QGdldG1lZXRpby5jb20NCk9SR0FOSVpFUjtDTj1DaHJpc3RvcGhlciBDYXJsc3NvbjptYWlsdG86eHh4DQpBVFRFTkRFRTtST0xFPVJFUS1QQVJUSUNJUEFOVDtDTj1DaHJpc3RvcGhlciBDYXJsc3NvbjptYWlsdG86eHh4DQpBQ1RJT047UlNWUD1UUlVFO0NOPUNocmlzdG9waGVyIENhcmxzc29uO1gtTlVNLUdVRVNUUz0wOm1haWx0bzp4eHgNCkRUU1RBUlQ6MjAxNzA4MDJUMDkwMDAwWg0KRFRFTkQ6MjAxNzA4MDJUMDkxNTAwWg0KRFRTVEFNUDoyMDE3MDgwMVQxNTQyMjJaDQpTVU1NQVJZOnRlc3QNCkRFU0NSSVBUSU9OOnRlc3QNCkxPQ0FUSU9OOlRlc3RpbmcgcmVzb3VyY2UNClNFUVVFTkNFOjENClNUQVRVUzpDT05GSVJNRUQNCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVI=

--b1_7f2ef0f72584f4006430793cafbac142d487260b5eeac5ab78c0058e50a9076e--

@Synchro
Copy link
Member

Synchro commented Aug 2, 2017

If you do just one or the other, do the buttons you're expecting appear in either? Do you have an example message that does work correctly that we could compare it with?

@christophercarlsson
Copy link

Im comparing to the reply above that @adsega posted, saying he could get it to work in Outlook. Buttons don't appear with just one or the other.

@Synchro
Copy link
Member

Synchro commented Aug 4, 2017

I've pushed some experimental changes in 6.0-ical - the main difference is the addition of a Content-Class header as suggested by articles here and here. Please can you give that a try?

@christophercarlsson
Copy link

Thank you for your continued efforts. Unfortunately it still does not work. The mail source is the following, but still no RSVP/ability to add to calendar in outlook nor Mail.

Subject: Calendar Invite: Test
Message-ID: d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87@laravel
X-Mailer: PHPMailer 6.0.0 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Class: urn:content-classes:calendarmessage
Content-Type: multipart/mixed;
boundary="b1_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87"
Content-Transfer-Encoding: 8bit

This is a multi-part message in MIME format.
--b1_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87
Content-Type: multipart/alternative;
boundary="b2_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87"

--b2_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87
Content-Type: text/plain; charset=us-ascii

test

--b2_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87
Content-Type: text/html; charset=us-ascii

test

--b2_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87
Content-Type: text/calendar; method=REQUEST; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-Class: urn:content-classes:calendarmessage

BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:Microsoft Exchange Server 2010
VERSION:2.0
BEGIN:VEVENT
UID:book-25@xxx
ORGANIZER;CN=Christopher Carlsson:mailto:xxx
ATTENDEE;ROLE=REQ-PARTICIPANT;CN=Christopher Carlsson:mailto:xxx
ACTION;RSVP=TRUE;CN=Christopher Carlsson;X-NUM-GUESTS=0:mailto:xxx
DTSTART:20170804T134500Z
DTEND:20170804T140000Z
DTSTAMP:20170804T112625Z
SUMMARY:Test
DESCRIPTION:test
LOCATION:Testresurs
SEQUENCE:1
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

--b2_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87--

--b1_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87
Content-Type: text/calendar; name="calendar.ics"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=calendar.ics

QkVHSU46VkNBTEVOREFSDQpNRVRIT0Q6UkVRVUVTVA0KUFJPRElEOk1pY3Jvc29mdCBFeGNoYW5nZSBTZXJ2ZXIgMjAxMA0KVkVSU0lPTjoyLjANCkJFR0lOOlZFVkVOVA0KVUlEOmJvb2stMjVAeHh4DQpPUkdBTklaRVI7Q049Q2hyaXN0b3BoZXIgQ2FybHNzb246bWFpbHRvOnh4eA0KQVRURU5ERUU7Uk9MRT1SRVEtUEFSVElDSVBBTlQ7Q049Q2hyaXN0b3BoZXIgQ2FybHNzb246bWFpbHRvOnh4eA0KQUNUSU9OO1JTVlA9VFJVRTtDTj1DaHJpc3RvcGhlciBDYXJsc3NvbjtYLU5VTS1HVUVTVFM9MDptYWlsdG86eHh4DQpEVFNUQVJUOjIwMTcwODA0VDEzNDUwMFoNCkRURU5EOjIwMTcwODA0VDE0MDAwMFoNCkRUU1RBTVA6MjAxNzA4MDRUMTEyNjI1Wg0KU1VNTUFSWTpUZXN0DQpERVNDUklQVElPTjp0ZXN0DQpMT0NBVElPTjpUZXN0cmVzdXJzDQpTRVFVRU5DRToxDQpTVEFUVVM6Q09ORklSTUVEDQpFTkQ6VkVWRU5UDQpFTkQ6VkNBTEVOREFS

--b1_d83d69dae575b544ae866adb06fa17e53e7014bfcc12978a468b83895932fa87--

@Synchro
Copy link
Member

Synchro commented Aug 4, 2017

Does anyone have known-working examples for all the places that we want this to work that they could share? I'm working pretty much blind here.

@Synchro
Copy link
Member

Synchro commented Aug 22, 2017

I happened to get sent an invitation from Apple's iCal service on iCloud. The email structure looks like this:

Content-Type: multipart/mixed; 
	boundary="----=_Part_889321_1826442293.1503391415807"

------=_Part_889321_1826442293.1503391415807
Content-Type: multipart/alternative; 
	boundary="----=_Part_889322_1826442187.1503391415807"

------=_Part_889322_1826442187.1503391415807
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
Content-Disposition: inline

text part

------=_Part_889322_1826442187.1503391415807
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
Content-Disposition: inline


HTML part

------=_Part_889322_1826442187.1503391415807--

------=_Part_889321_1826442293.1503391415807
Content-Type: text/calendar; method=REQUEST
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=iCal-20170822-014335.ics

ical part

------=_Part_889321_1826442293.1503391415807--

This message does nothing special in Mail on either macOS or iOS. There are buttons displayed, but they are just HTML from the HTML part, and the iCal part is shown as an attachment. Note that the text/calendar part is not part of the multipart/alternative structure - it's a simple attachment within the root multipart/mixed element. That said, while it did nothing within Mail, the Calendar app on macOS displayed a notification several minutes later containing close and accept buttons, though I have no way of telling if this was triggered by the email or one of my calendar subscriptions. What I really need is details of the MIME structure & headers that causes Outlook to do its thing.

@gunkire
Copy link

gunkire commented Oct 7, 2017

https://forums.phpfreaks.com/topic/157171-solved-phpmailer-custom-content/?p=829136

@Synchro
Copy link
Member

Synchro commented Oct 7, 2017

@gunkire The PHPMailer code is already doing the same as what's in that example.

@christophercarlsson
Copy link

christophercarlsson commented Nov 13, 2017

I've finally solved this outside of PHPMailer, using PHP's own mail function. The issue seems to have been that the VCALENDAR object needed to have a timezone specified - this gave me the RSVP buttons.

$reservation = Reservation::with('user')->with('resource')->find($id);
$boundary = "--" . md5(time());
$origin_format = 'Y-m-d H:i:s';
$format = 'Ymd\THis';

$headers = "From: My sender my@sender.com\n";
$headers .= "Reply-To: My sender my@sender.com\n";
$headers .= "Content-Type: text/calendar; method=REQUEST;boundary="" . $boundary . "";charset="utf-8"\n";
$headers .= "Content-Transfer-Encoding: 7bit\n";

$ical ="X-Mailer: Microsoft Office Outlook 12.0
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VTIMEZONE
TZID:UTC
BEGIN:STANDARD
DTSTART:20171010T000000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:+0000
TZOFFSETTO:+0000
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:20170310T000000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
TZOFFSETFROM:+0000
TZOFFSETTO:+0000
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;CN="'" . $reservation->user->name . "'";RSVP=TRUE:mailto:" . $reservation->user->email . "
CLASS:PUBLIC
CREATED:" . Carbon::now()->format('Ymd\THis') . "
DTEND;TZID="UTC":" . Carbon::createFromFormat($origin_format, $reservation->ends_at)->format($format) . "
DTSTAMP:" . Carbon::now()->format('Ymd\THis') . "
DTSTART;TZID="UTC":" . Carbon::createFromFormat($origin_format, $reservation->starts_at)->format($format) . "
LAST-MODIFIED:20171113T133000
LOCATION:" . $reservation->resource->label . "
ORGANIZER;CN=Meetio Book:mailto:my@sender.com
PRIORITY:5
SEQUENCE:1
SUMMARY:Updated: " . $reservation->title . "
TRANSP:OPAQUE
UID:" . str_random(40) . "
END:VEVENT
END:VCALENDAR";
$subject = $reservation->title;

$mail_sent = mail($reservation->user->email, $subject, $ical, $headers);

Hope this helps you solve the issue in PHPMailer.

@omocinteractive
Copy link

omocinteractive commented Jan 4, 2018

... is there any solution with PhpMailer 5.2? Maybe in the new version of PhpMailer?

@eltharin
Copy link

You can try to set those headers for PHPMAILER :
$mail->CharSet = 'utf-8';
$mail->ContentType = 'text/calendar;method=REQUEST';
$mail->Encoding = '7bit';

@Synchro
Copy link
Member

Synchro commented Dec 28, 2019

Look at the code; if you use PHPMailer’s iCal support, it adds exactly that header already.

@jdudley1123
Copy link

I think I've cracked it. Tested on Gmail and on Outlook. Both result in properly formatted calendar invites with RSVP buttons.

I don't know exactly why it works and other solutions don't, I just know that it does! I kept trying things from StackOverflow answers and suggestions in this thread and elsewhere until I got something that worked.

The VCALENDAR object looks like this:

BEGIN:VCALENDAR
PRODID:-//Mailer//NONSGML v1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20200523T080000Z
DTEND:20200523T090000Z
DTSTAMP:20200522T133929Z
ORGANIZER;CN="Joseph":mailto:joseph@example.com
UID:e8e8a1f77808cd0719daf26f973e556e@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Heidi";X-NUM-GUESTS=0:mailto:heidi@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="James";X-NUM-GUESTS=0:mailto:james@example.com
CREATED:20200522T133929Z
DESCRIPTION:This is a test invitation
LAST-MODIFIED:20200522T133929Z
SUMMARY:Test event
LOCATION:London
END:VEVENT
END:VCALENDAR

The code that produced it looks like this:

// Content
$location           = "London";
$date               = '20200523';
$startTime          = '0800';
$endTime            = '0900';
$subject            = 'Test event';
$desc               = 'This is a test invitation';

$organizer          = 'Joseph';

$organizer_email    = 'joseph@example.com';   
$participant_name_1 = 'Heidi';
$participant_email_1= 'heidi@example.com';
$participant_name_2 = 'James';
$participant_email_2= 'james@example.com';

//Be very careful with this string. You may need to add CLRF (\r\n) line breaks depending on how your server handles line endings.
$ical_content = 'BEGIN:VCALENDAR
PRODID:-//Mailer//NONSGML v1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:'.$date.'T'.$startTime.'00Z
DTEND:'.$date.'T'.$endTime.'00Z
DTSTAMP:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
ORGANIZER;CN="'.$organizer.'":mailto:'.$organizer_email.'
UID:' . md5(uniqid(mt_rand(), true)) . '@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="'.$participant_name_1.'";X-NUM-GUESTS=0:mailto:'.$participant_email_1.'
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="'.$participant_name_2.'";X-NUM-GUESTS=0:mailto:'.$participant_email_2.'
CREATED:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
DESCRIPTION:'.$desc.'
LAST-MODIFIED:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
SUMMARY:'.$subject.'
LOCATION:'.$location.'
END:VEVENT
END:VCALENDAR';

$mail->ContentType = 'text/calendar'; //This seems to be important for Outlook
$mail->Subject = 'Testing testing 123';
$mail->Body = 'Testing testing 321'; 
$mail->AltBody = $ical_content;
$mail->Ical = $ical_content;
$mail->addStringAttachment($ical_content, 'ical.ics', 'base64', 'application/ics; name="ical.ics"'); //This seems to be important for Gmail

//From
$mail->setFrom('joseph@example.com', 'Joseph');
$mail->addReplyTo('joseph@example.com', 'Joseph');

//Recipients
$mail->addAddress($participant_email_1, $participant_name_1);
$mail->addAddress($participant_email_2, $participant_name_2);

//Send
$mail->send();

@omocinteractive
Copy link

... this is what it looks like for me in Outlook 365 (for a single event):
screenshot 118

@vikas-wadhwa
Copy link

I'm actually concerned in regards to @omocinteractive answer, because I cannot seem to get Outlook to recognize the DESCRIPTION field, and it looks like the image @omocinteractive posted also isn't showing the description (Which I assume should show up right below the location line)

Anyone else having issues with Outlook calendar not showing the DESCRIPTION value?

@Synchro
Copy link
Member

Synchro commented Jun 17, 2020

We know that Outlook is a horrible buggy mess, but you'll get better responses about it from MS support forums rather than here.

@rohantapiyawala
Copy link

rohantapiyawala commented Jun 25, 2020

I think I've cracked it. Tested on Gmail and on Outlook. Both result in properly formatted calendar invites with RSVP buttons.

I don't know exactly why it works and other solutions don't, I just know that it does! I kept trying things from StackOverflow answers and suggestions in this thread and elsewhere until I got something that worked.

The VCALENDAR object looks like this:

BEGIN:VCALENDAR
PRODID:-//Mailer//NONSGML v1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20200523T080000Z
DTEND:20200523T090000Z
DTSTAMP:20200522T133929Z
ORGANIZER;CN="Joseph":mailto:joseph@example.com
UID:e8e8a1f77808cd0719daf26f973e556e@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Heidi";X-NUM-GUESTS=0:mailto:heidi@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="James";X-NUM-GUESTS=0:mailto:james@example.com
CREATED:20200522T133929Z
DESCRIPTION:This is a test invitation
LAST-MODIFIED:20200522T133929Z
SUMMARY:Test event
LOCATION:London
END:VEVENT
END:VCALENDAR

The code that produced it looks like this:

// Content
$location           = "London";
$date               = '20200523';
$startTime          = '0800';
$endTime            = '0900';
$subject            = 'Test event';
$desc               = 'This is a test invitation';

$organizer          = 'Joseph';

$organizer_email    = 'joseph@example.com';   
$participant_name_1 = 'Heidi';
$participant_email_1= 'heidi@example.com';
$participant_name_2 = 'James';
$participant_email_2= 'james@example.com';

//Be very careful with this string. You may need to add CLRF (\r\n) line breaks depending on how your server handles line endings.
$ical_content = 'BEGIN:VCALENDAR
PRODID:-//Mailer//NONSGML v1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:'.$date.'T'.$startTime.'00Z
DTEND:'.$date.'T'.$endTime.'00Z
DTSTAMP:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
ORGANIZER;CN="'.$organizer.'":mailto:'.$organizer_email.'
UID:' . md5(uniqid(mt_rand(), true)) . '@example.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="'.$participant_name_1.'";X-NUM-GUESTS=0:mailto:'.$participant_email_1.'
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="'.$participant_name_2.'";X-NUM-GUESTS=0:mailto:'.$participant_email_2.'
CREATED:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
DESCRIPTION:'.$desc.'
LAST-MODIFIED:' . gmdate('Ymd').'T'. gmdate('His') . 'Z
SUMMARY:'.$subject.'
LOCATION:'.$location.'
END:VEVENT
END:VCALENDAR';

$mail->ContentType = 'text/calendar'; //This seems to be important for Outlook
$mail->Subject = 'Testing testing 123';
$mail->Body = 'Testing testing 321'; 
$mail->AltBody = $ical_content;
$mail->Ical = $ical_content;
$mail->addStringAttachment($ical_content, 'ical.ics', 'base64', 'application/ics; name="ical.ics"'); //This seems to be important for Gmail

//From
$mail->setFrom('joseph@example.com', 'Joseph');
$mail->addReplyTo('joseph@example.com', 'Joseph');

//Recipients
$mail->addAddress($participant_email_1, $participant_name_1);
$mail->addAddress($participant_email_2, $participant_name_2);

//Send
$mail->send();

@jdudley1123 can you share how did u make RSVP button show up on outlook ? I tried the code u share and it doesnt execute. Im using classic php with files imported into the code. Will try with composer as well. Thanks in advance

@jdudley1123
Copy link

@rohantapiyawala The code above won't execute, you'll need to do all the normal PHPMailer things first (see the tutorial). Once you've got a functional $mail object setting the content type, body etc. as I've described should work.

@rohantapiyawala
Copy link

@rohantapiyawala The code above won't execute, you'll need to do all the normal PHPMailer things first (see the tutorial). Once you've got a functional $mail object setting the content type, body etc. as I've described should work.

@jdudley1123 : Thanks for ur input and the code previously shared. I was able to solve the issue with both Google Cal and Outlook. Now my code produces RSVP button for both of them. Part I was missing was "Ical" parameter. Now I can even edit and delete my events using the ics file and PHPMailer. Cheers!

@sneha-surve
Copy link

@rohantapiyawala @jdudley1123 Can you please share what you did to have RSVP buttons on outlook?

@rohantapiyawala
Copy link

rohantapiyawala commented May 24, 2023

@sneha-surve

If you can mail me your code I can help. Sharing a working code that I use to schedule meetings for my various committees:

BEGIN:VCALENDAR VERSION:2.0 PRODID://ABCD Events//iCal 2.1//EN METHOD:REQUEST X-WR-CALNAME:ABCD Event Calendar X-WR-TIMEZONE:America/New_York CALSCALE:GREGORIAN BEGIN:VTIMEZONE TZID:America/New_York TZURL:http://tzurl.org/zoneinfo-outlook/America/New_York X-LIC-LOCATION:America/New_York BEGIN:DAYLIGHT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:EDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:EST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT TRANSP:OPAQUE CREATED:20230423T045348Z UID:WGFG20230423045348 SUMMARY:WGFG catch up ABCD Event DTSTART;TZID=America/New_York:20230426T170000 DTEND;TZID=America/New_York:20230426T180000 LOCATION;ENCODING=QUOTED-PRINTABLE: DTSTAMP:20230423T045348Z ORGANIZER;CN=ABCD Events:mailto:calendarbot@abcd.org ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=<email>;X-NUM-GUESTS=0:mailto:<email> STATUS:CONFIRMED DESCRIPTION:A. Want to join the meeting from your computer, tablet or smartphone? SEQUENCE:0 BEGIN:VALARM DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT10M ACTION:DISPLAY END:VALARM END:VEVENT END:VCALENDAR

@sneha-surve
Copy link

sneha-surve commented May 24, 2023

$ical_content = "BEGIN:VCALENDAR
VERSION:2.0
PRODID://Drupal iCal API//EN
BEGIN:VEVENT
UID:http://www.icalmaker.com/event/d8fefcc9-a576-4432-8b20-40e90889affd
DTSTAMP:20230524T045941Z
DTSTART:20230525T060000Z
DTEND:20230525T100000Z
SUMMARY:Party in Daawat
LOCATION:Hotel Daawat, Ground Floor, Phase 5, Sector 59, Near Post Office, Mohali 160059.
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Ayush Mehr
 otra:mailto:xxxxxx@gmail.com
DESCRIPTION:Dinner
END:VEVENT
END:VCALENDAR";
$mail = new PHPMailer(true);

// Recipients.
$mail->setfrom('xxxxx@gmail.com');
$mail->addAddress('xxx@gmail.com');
$mail->addreplyto('xx@xxx.com');
// Content.
// Set email format to HTML.
$mail->isHTML(TRUE);
$mail->isSMTP();
// Set the SMTP server to send through.
$mail->Host = 'smtp-mail.outlook.com';
// Enable SMTP authentication.
$mail->SMTPAuth = TRUE;
// SMTP username.
$mail->Username = 'xxxxx@gmail.com';
// SMTP password.
$mail->Password = 'xxxxxx;
// Enable implicit TLS encryption.
$mail->SMTPSecure = 'tls';
$mail->Port       = '587';
// $mail->CharSet = 'UTF-8';

// This seems to be important for Outlook.
// $mail->ContentType = 'text/calendar';
$mail->Subject     = 'Here is the subject';
$message           = 'This is the HTML message body <b>in bold!</b>';
$mail->msgHTML($message);
$mail->AltBody = $ical_content;
$mail->Ical = $ical_content;
// For sending ical.
if (!empty($ical_content)) {
  $mail->addStringAttachment($ical_content, 'ical.ics', 'base64', 'text/calendar');
}

$mail->send();`

@rohantapiyawala My sample code is as mentioned above. I need to add the calendar event in Outlook, but currently its coming as ICS file attachment. What can be done here. Pls help. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests