tags:

views:

78

answers:

1

I use the following emailing function with Eudora. For some reason the attachment file name is renamed to be something else. How can I make sure the attachment file name remains intact?

function SendMailMAPI(const Subject, Body, FileName, SenderName, SenderEMail, 
                  RecepientName, RecepientEMail: String) : Integer; 
var 
  message: TMapiMessage; 
  lpSender, 
  lpRecepient: TMapiRecipDesc; 
  FileAttach: TMapiFileDesc; 
  SM: TFNMapiSendMail; 
  MAPIModule: HModule; 
begin 
  FillChar(message, SizeOf(message), 0); 
  with message do 
  begin 
    if (Subject<>'') then 
    begin 
      lpszSubject := PChar(Subject) 
    end; 
    if (Body<>'') then 
    begin 
      lpszNoteText := PChar(Body) 
    end; 
    if (SenderEMail<>'') then 
    begin 
      lpSender.ulRecipClass := MAPI_ORIG; 
      if (SenderName='') then 
      begin 
        lpSender.lpszName := PChar(SenderEMail) 
      end 
      else 
      begin 
        lpSender.lpszName := PChar(SenderName) 
      end; 
      lpSender.lpszAddress := PChar('SMTP:'+SenderEMail); 
      lpSender.ulReserved := 0; 
      lpSender.ulEIDSize := 0; 
      lpSender.lpEntryID := nil; 
      lpOriginator := @lpSender; 
    end; 
    if (RecepientEMail<>'') then 
    begin 
      lpRecepient.ulRecipClass := MAPI_TO; 
      if (RecepientName='') then 
      begin 
        lpRecepient.lpszName := PChar(RecepientEMail) 
      end 
      else 
      begin 
        lpRecepient.lpszName := PChar(RecepientName) 
      end; 
      lpRecepient.lpszAddress := PChar('SMTP:'+RecepientEMail); 
      lpRecepient.ulReserved := 0; 
      lpRecepient.ulEIDSize := 0; 
      lpRecepient.lpEntryID := nil; 
      nRecipCount := 1; 
      lpRecips := @lpRecepient; 
    end 
    else 
    begin 
      lpRecips := nil 
    end; 
    if (FileName='') then 
    begin 
      nFileCount := 0; 
      lpFiles := nil; 
    end 
    else 
    begin 
      FillChar(FileAttach, SizeOf(FileAttach), 0); 
      FileAttach.nPosition := Cardinal($FFFFFFFF); 
      FileAttach.lpszPathName := PChar(FileName); 
      nFileCount := 1; 
      lpFiles := @FileAttach; 
    end; 
  end; 
  MAPIModule := LoadLibrary(PChar(MAPIDLL)); 
  if MAPIModule=0 then 
  begin 
    Result := -1 
  end 
  else 
  begin 
    try 
      @SM := GetProcAddress(MAPIModule, 'MAPISendMail'); 
      if @SM<>nil then 
      begin 
        Result := SM(0, Application.Handle, message, MAPI_DIALOG or 
                     MAPI_LOGON_UI, 0); 
      end 
      else 
      begin 
        Result := 1 
      end; 

    finally 
      FreeLibrary(MAPIModule); 
    end; 
  end; 
  if Result<>0 then 
  begin 
    MessageDlg('Error sending mail ('+IntToStr(Result)+').', mtError, [mbOk], 
               0) 
  end; 
+1  A: 

You have to set FileAttach.lpszFileName to the name you want your recipient to see. If you don't do that an attachment like "C:\Document And Settings\MyUser\Local Settings\Temp\Hello.pdf" will look like "C__DOCUME~1_MyUser_LOCALS~1_Temp_Hello.pdf" to the recipient (this is probably different per e-mailclient ).

So set FileAttach.lpszPathName to contain only the filename:

begin 
  FillChar(FileAttach, SizeOf(FileAttach), 0); 
  FileAttach.nPosition := Cardinal($FFFFFFFF); 
  FileAttach.lpszPathName := PChar(FileName); 
  FileAttach.lpszFileName := PChar(ExtractFileName(FileName)); //add this
  nFileCount := 1; 
  lpFiles := @FileAttach; 
end;

The recipient will now see an attachment with the name "Hello.pdf" instead of "C__DOCUME~1_MyUser_LOCALS~1_Temp_Hello.pdf".

The_Fox
Thanks this did not affect anything, could it be a limitation of EUDORA being used? its giving short random names..
Tom
Tom, to determine whether this is Eudora's fault, send your e-mail through a different client. Does it still have the same attachment names? I'd use Wireshark to confirm the exact contents your program sends to the SMTP server. If Wireshark shows the correct file names, and multiple different clients receive the wrong file names, then you're left with the SMTP, POP, or IMAP servers altering the names mid-stream, or maybe a virus-scanning proxy on the client.
Rob Kennedy
The_Fox's example is assigning a temporary pointer to the lpszFileName value. By the time MAPI sees the value, the pointer will not be valid anymore. Assign the result of ExtractFileName() to a String variable first, then PChar() that when assigning lpszFileName.
Remy Lebeau - TeamB
@Remy Lebeau: I actually tried it out to see if it invalidated, but the value from ExtractFileName was put somewhere on the stack and is only cleared at the end of the method. But is indeed better to put it into a variable.
The_Fox