Do not get iCal attachment in gmail properly

4.1k views Asked by At

I'm trying to send an invitation through an email using iCal. My email sending is working properly but I do not get the iCal attachment properly. Following is my php function which handles the email sending.

    function sendIcalEmail($firstname,$lastname,$email,$meeting_date,$meeting_name,$meeting_duration) {

        $from_name = "Sampath";
        $from_address = "my email";
        $subject = "Meeting Booking"; //Doubles as email subject and meeting subject in calendar
        $meeting_description = "Here is a brief description of my meeting.";
        $meeting_location = "My Office"; //Where will your meeting take place


        //Convert MYSQL datetime and construct iCal start, end and issue dates
        $meetingstamp = strtotime($meeting_date . " UTC");    
        $dtstart= gmdate("Ymd\THis\Z",$meetingstamp);
        $dtend= gmdate("Ymd\THis\Z",$meetingstamp+$meeting_duration);
        $todaystamp = gmdate("Ymd\THis\Z");

        //Create unique identifier
        $cal_uid = date('Ymd').'T'.date('His')."-".rand()."@example.com";

        //Create Mime Boundry
        $mime_boundary = "----Meeting Booking----".md5(time());

        //Create Email Headers
        $headers = "From: ".$from_name." <".$from_address.">\n";
        $headers .= "Reply-To: ".$from_name." <".$from_address.">\n";

        $headers .= "MIME-Version: 1.0\n";
        $headers .= "Content-Type: multipart/alternative; boundary=\"$mime_boundary\"\n";
        $headers .= "Content-class: urn:content-classes:calendarmessage\n";

        //Create Email Body (HTML)
        $message .= "--$mime_boundary\n";
        $message .= "Content-Type: text/html; charset=UTF-8\n";
        $message .= "Content-Transfer-Encoding: 8bit\n\n";

        $message .= "<html>\n";
        $message .= "<body>\n";
        $message .= '<p>Dear '.$firstname.' '.$lastname.',</p>';
        $message .= '<p>Here is my HTML Email / Used for Meeting Description</p>';    
        $message .= "</body>\n";
        $message .= "</html>\n";
        $message .= "--$mime_boundary\n";

        //Create ICAL Content (Google rfc 2445 for details and examples of usage) 
        $ical =    "BEGIN:VCALENDAR\n".
           "PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN\n".
           "VERSION:2.0\n".
           "METHOD:PUBLISH\n".
           "BEGIN:VEVENT\n".
           "ORGANIZER:MAILTO:".$from_address."\n".
           "DTSTART:".$dtstart."\n".
           "DTEND:".$dtend."\n".
           "LOCATION:".$meeting_location."\n".
           "TRANSP:OPAQUE\n".
           "SEQUENCE:0\n".
           "UID:".$cal_uid."\n".
           "DTSTAMP:".$todaystamp."\n".
           "DESCRIPTION:".$meeting_description."\n".
           "SUMMARY:".$subject."\n".
           "PRIORITY:5\n".
           "CLASS:PUBLIC\n".
           "END:VEVENT\n".
           "END:VCALENDAR";   

        $message .= 'Content-Type: text/calendar;name="meeting.ics";method=REQUEST;charset=utf-8\n';
        $message .= 'Content-Type: text/calendar;name="meeting.ics";method=REQUEST\n';
        $message .= "Content-Transfer-Encoding: 8bit\n\n";
        $message .= $ical;            

        //SEND MAIL

        require_once "./swiftmailer/swift_required.php";

        $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, "ssl")
            ->setUsername('my email')
            ->setPassword('password');

        $mailer = Swift_Mailer::newInstance($transport);

        $sendMessage = Swift_Message::newInstance('Meeting Invitation')
           ->setFrom(array($from_address => 'Sampath B. Herath'))
           ->setTo(array($email))
           ->setBody($message);

        $result = $mailer->send($sendMessage);

        if($result) {
            return true;
        } else {
            return false;
        }   
    }

following is what I can see in result email.

------Meeting Booking----2a43c2697329a93848be0ba81582a3cb
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<html>
<body>
<p>Dear Sampath Herath,</p><p>Here is my HTML Email / Used for Meeting Description</p>    </body>
</html>
------Meeting Booking----2a43c2697329a93848be0ba81582a3cb
Content-Type: text/calendar;name="meeting.ics";method=REQUEST;charset=utf-    8\nContent-Type: text/calendar;name="meeting.ics";method=REQUEST\nContent-Transfer- Encoding: 8bit

BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
BEGIN:VEVENT
ORGANIZER:MAILTO:[email protected]
DTSTART:20130819T134000Z
DTEND:20130819T144000Z
LOCATION:My Office
TRANSP:OPAQUE
SEQUENCE:0
UID:[email protected]
DTSTAMP:20130819T074345Z
DESCRIPTION:Here is a brief description of my meeting.
SUMMARY:Meeting Booking
PRIORITY:5
CLASS:PUBLIC
END:VEVENT
END:VCALENDAR

What is the exact issue with my code?

2

There are 2 answers

0
Sampath Bandara Herath On

I have completed my task and following is how I have done it.

Script 1 : index.php

<?php
include ("iCal.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>iCal Test</title>
</head>
<body>
<?php
    //$firstname is the first name of target
    //$lastname is the last name of target
    //$email is the targets email address
    //$meeting_date is straight from a DATETIME mysql field and assumes UTC.
    //$meeting_name is the name of your meeting
    //$meeting_duretion is the duration of your meeting in seconds (3600 = 1 hour)

    $firstname = "Sampath";
    $lastname = "Sampath B. Herath";
    $email = "my email address here";
    $meeting_date = "2013-08-20 13:00:00"; //mysql format
    $meeting_name = "Hello";
    $meeting_duration = 3600;

    $result = sendIcalEmail($firstname,$lastname,$email,$meeting_date,$meeting_name,$meeting_duration);

    if($result) {
        echo "Email sent successfully.";
    } else {
        echo "A problem occured sending email";
    }   
?>
</body>
</html>

Script 2 : ical.php

<?php
function sendIcalEmail ($firstname, $lastname, $email, $meeting_date, $meeting_name, $meeting_duration)  {
    $from_name = "My Name";
    $from_address = "my email address here";
    $subject = "Meeting Booking"; //Doubles as email subject and meeting subject in calendar
    $meeting_description = "Here is a brief description of my meeting.";
    $meeting_location = "My Office"; //Where will your meeting take place

    //Convert MYSQL datetime and construct iCal start, end and issue dates
    $meetingstamp = strtotime($meeting_date . " UTC");
    $dtstart= gmdate("Ymd\THis\Z",$meetingstamp);
    $dtend= gmdate("Ymd\THis\Z",$meetingstamp+$meeting_duration);
    $todaystamp = gmdate("Ymd\THis\Z");

    //Create unique identifier
    $cal_uid = date('Ymd').'T'.date('His')."-".rand()."@mydomain.com";

    //Create Mime Boundry
    $mime_boundary = "Meeting Booking-".md5(time());

    //Create Email Headers
    $headers = "From: ".$from_name." <".$from_address.">\n";
    $headers .= "Reply-To: ".$from_name." <".$from_address.">\n";

    $headers .= "MIME-Version: 1.0\n";
    $headers .= "Content-Type: multipart/alternative; boundary=\"$mime_boundary\"\n";
    $headers .= "Content-class: urn:content-classes:calendarmessage\n";

    //Create Email Body (HTML)
    $message .= "--$mime_boundary\n";
    $message .= "Content-Type: text/html; charset=UTF-8\n";
    $message .= "Content-Transfer-Encoding: 8bit\n\n";
    $message .= "Content-Transfer-Encoding: quoted-printable\n\n";

    $message .= "<html>\n";
    $message .= "<body>\n";
    $message .= "<p>Dear ".$firstname." ".$lastname.",</p>\n";
    $message .= "<p>Here is my HTML Email / Used for Meeting Description</p>\n";
    $message .= "</body>\r\n";
    $message .= "</html>\r\n";
    $message .= "--$mime_boundary\r\n";

    $ical = 'BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:'.$dtstart.'
DTEND:'.$dtend.'
DTSTAMP:'.$todaystamp.'
ORGANIZER:MAILTO:'.$from_address.'
UID:'.$cal_uid.'
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=
 TRUE;CN=Sampath Herath;X-NUM-GUESTS=0:mailto:[email protected]
DESCRIPTION:'.$meeting_description.'
LOCATION:'.$meeting_location.'
SEQUENCE:0
SUMMARY:'.$subject.'
PRIORITY:5
CLASS:PUBLIC
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR';

    $message .= 'Content-Type: text/calendar; name="meeting.ics"; method=REQUEST; charset=utf-8\n';
    $message .= "Content-Transfer-Encoding: 8bit\n\n";
    $message .= "Content-Transfer-Encoding: quoted-printable\n\n";
    $message .= $ical;

    //SEND MAIL
    $mail_sent = @mail( $email, $subject, $message, $headers );

    if($mail_sent)     {
        return true;
    } else {
        return false;
    }
}

I used sendmail server to test the email sending.

I referred this post to complete the task.

1
Arnaud Quillaud On

First of all, you output the content-type of the icalendar bodypart twice.

Then, this content-type mentions a method=REQUEST while the actual iCalendar contains a METHOD=PUBLISH.

I suspect that gmail understands only METHOD=REQUEST in which case, you need to look at the mandatory properties for such an iTIP message. The most obvious one is the lack of an ATTENDEE property. See https://www.rfc-editor.org/rfc/rfc5546#section-3.2.2 for the full list.