Adding attachments to E-mail bound for Evernote E-mail address defeats HTML content type declaration with Indy TIdSMTP component

delphi, evernote, indy-9, smtp

Solution

Your code is not setting up `TIdMessage` correctly when attachments are present. Try this instead:

function easySendEmail( 
                theIdSmtp               : TIdSmtp; 
                destEMailAddress        : string; 
                theSubject              : string; 
                theBody                 : string; 
                emailServerSettings     : TEmailServerSettingsRecord; 
                aryAttachmentFilenames  : TDynamicStringArray; 
                connectTimeOut_ms       : integer; 
                bUseEHLO                : boolean; 
                authLoginType           : TAuthenticationType): boolean; 
var 
  IdMsg: TIdMessage; 
  i: integer; 
begin 
  destEMailAddress := Trim(destEMailAddress); 
  if destEMailAddress = '' then 
    raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The destination E-mail address is empty.'); 

  theSubject := Trim(theSubject); 
  if theSubject = '' then 
    raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The subject line is empty.'); 

  theBody := Trim(theBody); 
  if theBody = '' then 
    raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The message body is empty.'); 

  IdMsg := TIdMessage.Create(nil); 
  try 
    with emailServerSettings do 
    begin 
      // Build a test message and send it. 
      IdMsg.Recipients.EMailAddresses := destEMailAddress; 
      { 
        Most SMTP servers require the sending E-mail address as the 
        user name for the authentication.  However, if we 
        encounter one that doesn't work this way then re-using 
        the authentication user name as the From address 
        will not work. 
      } 
      IdMsg.From.Name    := APPLICATION_NAME_EVERMAIL; 
      IdMsg.From.Address := user_name; 
      IdMsg.Subject := theSubject; 

      // Add the attachments. 
      if Length(aryAttachmentFilenames) > 0 then 
      begin 
        with TIdText.Create(IdMsg.MessageParts, nil) do
        begin
          Body.Text := 'An HTML viewer is required to see this message'; 
          ContentType := 'text/plain';
        end; 

        with TIdText.Create(IdMsg.MessageParts, nil) do
        begin
          Body.Text := theBody; 
          ContentType := 'text/html';
        end; 

        // Add each attachment. 
        for i := Low(aryAttachmentFilenames) to High(aryAttachmentFilenames) do 
          TIdAttachment.Create(IdMsg.MessageParts, aryAttachmentFilenames[i]); 

        IdMsg.ContentType := 'multipart/mixed'; 
      end else
      begin
        IdMsg.Body.Text := theBody; 
        IdMsg.ContentType := 'text/html'; 
      end; // if Length(aryAttachmentFilenames) > 0 then 

      theIdSmtp.Host := host; 
      theIdSmtp.Username := user_name; 
      theIdSmtp.Password := password; 
      theIdSmtp.Port := port_number; 
      // Use EHLO method. 
      theIdSmtp.UseEhlo := true; 
      // Login method of authentication. 
      theIdSmtp.AuthenticationType := atLogin; 

      // Connect to the desired SMTP server.  N second time-out. 
      theIdSmtp.Connect(connectTimeOut_ms); 
      try
        // Send it. 
        theIdSmtp.Send(IdMsg); 

        // If we got here than the test succeeded.  Set the flag 
        //  indicating the current settings are valid. 
        Result := true; 

      finally
        theIdSmtp.Disconnect; 
      end;
    end; // with emailServerSettings do 
  finally 
    IdMsg.Free; 
  end; // try 
end; 

Problem

I have a Delphi 6 application that generates E-mails that I send to my Evernote E-mail address, a special E-mail address for sending documents via E-mail so that they are stored automatically into my Evernote account. I have successfully created HTML documents and sent them to my Evernote E-mail address using the Indy 9.x TIdSMTP component. I set the Content-Type to 'text/html'. It works fine as long as I don't add any attachments to the E-mail. As soon as I add an attachment, something about the generated E-mail makes the Evernote web interface interpret the E-mail as raw HTML. In other words, I see the raw HTML in the document display area as if I had done "view-source" in a browser, instead of seeing a rendered web page. The E-mail attachments I am adding are an AVI file and a WAV file if that matters. When I do add attachments both of them show up properly at the bottom of the E-mail in the Evernote web display area. To repeat, as soon as I don't add attachments the document shows up as a pretty web page in the Evernote web interface. If I add attachments, I see raw HTML. Can anyone suggest something I can try to fix this problem? I have enclosed the code I use to send the generated document to my Evernote E-mail address below. The variable named body contains a fully formatted HTML document. UPDATE: I sent the E-mail to a non-Evernote E-mail address so I could see the raw E-mail message. I turns out that adding attachments makes TIdSMTP change the Content-Type of the first part of the multi-part E-mail it generates back to 'text/plain' despite the fact I set it to 'text/html' in my code when I create the message. I'm going to have a look at the Indy source and see if I can figure out what is going wrong. ``` function easySendEmail( theIdSmtp : TIdSmtp; destEMailAddress : string; subject : string; body : string; emailServerSettings : TEmailServerSettingsRecord; aryAttachmentFilenames : TDynamicStringArray; connectTimeOut_ms : integer; bUseEHLO : boolean; authLoginType : TAuthenticationType): boolean; var IdMsg: TIdMessage; aryAttachments: TDynamicIdAttachmentArray; i: integer; begin aryAttachments := nil; IdMsg := nil; destEMailAddress := Trim(destEMailAddress); if destEMailAddress = '' then raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The destination E-mail address is empty.'); subject := Trim(subject); if subject = '' then raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The subject line is empty.'); body := Trim(body); if body = '' then raise Exception.Create('(TframeEmailServerSettings.easySendEmail) The message body is empty.'); try with emailServerSettings do begin // Build a test message and send it. IdMsg := TIdMessage.Create(nil); IdMsg.Recipients.EMailAddresses := destEMailAddress; { Most SMTP servers require the sending E-mail address as the user name for the authentication. However, if we encounter one that doesn't work this way then re-using the authentication user name as the From address will not work. } IdMsg.From.Name := APPLICATION_NAME_EVERMAIL; IdMsg.From.Address := user_name; IdMsg.Subject := subject; IdMsg.Body.Text := body; IdMsg.ContentType := 'text/html'; // IdMsg.ContentType := 'text/plain'; theIdSmtp.Host := host; theIdSmtp.Username := user_name; theIdSmtp.Password := password; theIdSmtp.Port := port_number; // Use EHLO method. theIdSmtp.UseEhlo := true; // Login method of authentication. theIdSmtp.AuthenticationType := atLogin; // Add the attachments. // >>> If I comment out the code below the document shows // up as a rendered web page in the Evernote web interface. // If I uncomment it and therefore add attachments, the // document shows up as raw HTML. { if Length(aryAttachmentFilenames) > 0 then begin SetLength(aryAttachments, Length(aryAttachmentFilenames)); for i := Low(aryAttachmentFilenames) to High(aryAttachmentFilenames) do // Add each attachment. aryAttachments[i] := TIdAttachment.Create(IdMsg.MessageParts, aryAttachmentFilenames[i]); end; // if Length(aryAttachmentFilenames) > 0 then } // Connect to the desired SMTP server. N second time-out. theIdSmtp.Connect(connectTimeOut_ms); // Send it. theIdSmtp.Send(IdMsg); // If we got here than the test succeeded. Set the flag // indicating the current settings are valid. Result := true; end; // with mergeEditsWithOriginal do finally theIdSmtp.Disconnect; if Assigned(IdMsg) then IdMsg.Free; end; // try end; ```

Original source