tags:

views:

572

answers:

3

I have tried to embed the icalendar code in a email to be sent via indy with a content type text/calendar but it just hangs on the encoding of the email when I add as an attachment it just arrives as an attachment and does not prompt as other calendar request do. Has any one got example code of how to do calendar requests via indy?

+2  A: 

@David, the email client will recognize as a calendar request the attachment if you set the property to ContentType:='text/calendar', see this link for the iCalendar format Specification

see this sample code (tested en Delphi 2010)

program SendMailWithCalendarRequest;
{$APPTYPE CONSOLE}


uses
  IdSMTP,
  Classes,
  DateUtils,
  IdAttachmentFile,
  IdMessage,
  SysUtils;

 procedure SendCalendarRequest;
 var
  SMTP        : TIdSMTP;
  MailMessage : TIdMessage;
  Calendar    : TStrings;
  CalendarFile: String;
  Attachment  : TIdAttachmentFile;
  SenderMail  : String;
 begin
    SenderMail:='[email protected]';
    CalendarFile:=ExtractFilePath(ParamStr(0))+'\appmnt.vcs';
    Calendar:=TStringList.Create;
    try
        Calendar.Add('BEGIN:VCALENDAR');
        Calendar.Add('VERSION:1.0');
        Calendar.Add('BEGIN:VEVENT');
        Calendar.Add('ORGANIZER:MAILTO:'+SenderMail);
        Calendar.Add('DTStart:'+FormatDateTime('YYYY-DD-DD',Now));
        Calendar.Add('DTEnd:'+FormatDateTime('YYYY-DD-DD',  Tomorrow));
        Calendar.Add('Location;ENCODING=QUOTED-PRINTABLE: My home');
        Calendar.Add('UID:'+FormatDateTime('YYYY-DD-DD',Now)+FormatDateTime('YYYY-DD-DD',Tomorrow));
        Calendar.Add('SUMMARY:Appointment Reminder');
        Calendar.Add('DESCRIPTION:Test message');
        Calendar.Add('PRIORITY:5');
        Calendar.Add('END:VEVENT');
        Calendar.Add('END:VCALENDAR');
        Calendar.SaveToFile(CalendarFile);
    finally
    Calendar.Free;
    end;

   SMTP:= TIdSMTP.Create(nil);
   MailMessage := TIdMessage.Create(nil);
   try
     SMTP.Host := 'smtp.mailserver.com';
     SMTP.Port := 25;
     SMTP.Username:='the account';
     SMTP.Password:='the password';
     SMTP.AuthType:=satDefault;
     MailMessage.From.Address := SenderMail;
     MailMessage.Recipients.EMailAddresses := 'the Recipient';
     MailMessage.Subject   := 'Send calendar';
     MailMessage.Body.Text := '';
     Attachment:=TIdAttachmentFile.Create(MailMessage.MessageParts, CalendarFile) ;
     Attachment.ContentType:='text/calendar';//set the content type to text/calendar
     try
       try
         SMTP.Connect;
         SMTP.Send(MailMessage) ;
         Writeln('OK')
       except on E:Exception do
         Writeln(0, 'ERROR: ' + E.Message) ;
       end;
     finally
       if SMTP.Connected then SMTP.Disconnect;
     end;
   finally
    SMTP.Free;
    MailMessage.Free;
   end;

 end;

begin
  try
    SendCalendarRequest;
    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
RRUZ
A: 

Thanks for that. I run you example code to get started, but I will eventually need to embed the request in an email because I have a windows service that periodically sends emails and I would rather have the service not create a temporary file because of its work load (200+ users of the system sending out orders. BTW not spam or bulk mail just high service requests).

David Lindsey
Don't reply to an answer with another answer, instead, add a comment to the original answer.
Eduardo Scoz
sorry tried to reply in add comment area but nothing happened .. now it works
David Lindsey
A: 

Here is an alternative to RRUZ's example:

program SendMailWithCalendarRequest; 
{$APPTYPE CONSOLE} 

uses 
  IdSMTP, 
  Classes, 
  DateUtils, 
  IdMessage, 
  SysUtils; 

 procedure SendCalendarRequest; 
 var 
  SMTP        : TIdSMTP; 
  MailMessage : TIdMessage; 
 begin 
   SMTP:= TIdSMTP.Create(nil); 
   MailMessage := TIdMessage.Create(nil); 
   try 
     SMTP.Host := 'smtp.mailserver.com'; 
     SMTP.Port := 25; 
     SMTP.Username := 'the account'; 
     SMTP.Password := 'the password'; 
     SMTP.AuthType := satDefault; 
     MailMessage.From.Address := '[email protected]'; 
     MailMessage.Recipients.EMailAddresses := 'the Recipient'; 
     MailMessage.Subject := 'Send calendar'; 
     MailMessage.Body.Add('BEGIN:VCALENDAR'); 
     MailMessage.Body.Add('VERSION:1.0'); 
     MailMessage.Body.Add('BEGIN:VEVENT'); 
     MailMessage.Body.Add('ORGANIZER:MAILTO:'+SenderMail); 
     MailMessage.Body.Add('DTStart:'+FormatDateTime('YYYY-DD-DD',Now)); 
     MailMessage.Body.Add('DTEnd:'+FormatDateTime('YYYY-DD-DD',  Tomorrow)); 
     MailMessage.Body.Add('Location;ENCODING=QUOTED-PRINTABLE: My home'); 
     MailMessage.Body.Add('UID:'+FormatDateTime('YYYY-DD-DD',Now)+FormatDateTime('YYYY-DD-DD', Tomorrow)); 
     MailMessage.Body.Add('SUMMARY:Appointment Reminder'); 
     MailMessage.Body.Add('DESCRIPTION:Test message'); 
     MailMessage.Body.Add('PRIORITY:5'); 
     MailMessage.Body.Add('END:VEVENT'); 
     MailMessage.Body.Add('END:VCALENDAR'); 
     MailMessage.ContentType := 'text/calendar';
     SMTP.Connect; 
     try 
       try 
         SMTP.Send(MailMessage) ; 
         Writeln('OK') 
       except on E:Exception do 
         Writeln(0, 'ERROR: ' + E.Message) ; 
       end; 
     finally 
       SMTP.Disconnect; 
     end; 
   finally 
    SMTP.Free; 
    MailMessage.Free; 
   end; 
 end; 

begin 
  try 
    SendCalendarRequest; 
    readln; 
  except 
    on E: Exception do 
      Writeln(E.ClassName, ': ', E.Message); 
  end; 
end. 
Remy Lebeau - TeamB
Thanks, I ran RRUZ program kind of worked in gmail, but outlook when retrieving the email just terminates. More specific. The service auto sends email from the server using Indy each email has a text/plain part, the text/html part and optionally attachments. This works fine. When trying to incorporate the ical on the end similar to example with content text/calendar; method=request as a final part the program freezes after encoding message for the first parts but a problem on the calendar part.The message part as if a text/plain with the tstrings of the ical and the content as mentioned.
David Lindsey
Then you are likely not filling in the TIdMessage correctly, please show your actual code.
Remy Lebeau - TeamB
my code below, added part is the last after attachments ectProcedure Emailer.BuildCalendar(Msg_In : TIdMessage); var s: TStrings;const TAB = #9;begin try s:= TStringList.Create; s.Add('BEGIN:VCALENDAR');... other lines added here ..... s.Add('END:VCALENDAR'); // Create the Calendar parts with TIdText.Create(Msg_In.MessageParts, s) do begin ContentType := 'text/calendar; method="REQUEST"; charset="UTF-8"'; ParentPart := 0 ; // IdText.CharSet end; finally s.free; end;end;.... with thanks
David Lindsey
You did not show your entire TIdMessage code. However, you are setting ParentPart:=0, which is putting the attachment at the wrong level of the message. ParentPart is used for nesting, and the attachment should not be nested. Leave ParentPart set to -1.
Remy Lebeau - TeamB
That was it. Changed ParentPart and now works ok. How embarrassing. Thanks very much for all your assistance. Regards David
David Lindsey