Main Topics
Browse All TopicsHi,
I am trying to send an email from within delphi, silently, without using SMTP. I am currently using MAPI calls which work well except that when sending to a client using Outlook Express and a Linux mail server, the attachments come through as garbage or 'winmail.dat' and a wierd MIME type header.
All of the examples I have looked at pass through NIL as the filetype for the attachments sent to MAPI. Does anyone have any alternatives to using MAPI or know how to solve the problem with the attachments.
Any help would be much appreciated.
Thanks
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
Thanks for the reply, but SMTP does not help us. We can already send using either SMTP or MAPI, the problem is that our client wants to have the emails in their 'Sent items' folder on the local machine doing the sending, thus, MAPI must be used unless there is a way to get messages sent via SMTP into 'sent items' ?
Thanks
function SendMail(const Subject, Body, FileName,
SenderName, SenderEMail,
RecipientName, RecipientEMail: string): Integer;
var
Message: TMapiMessage;
lpSender, lpRecipient: TMapiRecipDesc;
FileAttach: TMapiFileDesc;
SM: TFNMapiSendMail;
MAPIModule: HModule;
begin
FillChar(Message, SizeOf(Message), 0);
with Message do
begin
if (Subject <> '') then
lpszSubject := PChar(Subject);
if (Body <> '') then
lpszNoteText := PChar(Body);
if (SenderEmail <> '') then
begin
lpSender.ulRecipClass := MAPI_ORIG;
if (SenderName = '') then
lpSender.lpszName := PChar(SenderEMail)
else
lpSender.lpszName := PChar(SenderName);
lpSender.lpszAddress := PChar(SenderEmail);
lpSender.ulReserved := 0;
lpSender.ulEIDSize := 0;
lpSender.lpEntryID := nil;
lpOriginator := @lpSender;
end;
if (RecipientEmail <> '') then
begin
lpRecipient.ulRecipClass := MAPI_TO;
if (RecipientName = '') then
lpRecipient.lpszName := PChar(RecipientEMail)
else
lpRecipient.lpszName := PChar(RecipientName);
lpRecipient.lpszAddress := PChar(RecipientEmail);
lpRecipient.ulReserved := 0;
lpRecipient.ulEIDSize := 0;
lpRecipient.lpEntryID := nil;
nRecipCount := 1;
lpRecips := @lpRecipient;
end
else
lpRecips := nil;
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
Result := -1
else
try
@SM := GetProcAddress(MAPIModule,
if @SM <> nil then
begin
Result := SM(0, Application.Handle, Message, MAPI_DIALOG or MAPI_LOGON_UI, 0);
end
else
Result := 1;
finally
FreeLibrary(MAPIModule);
end;
if Result <> 0 then
MessageDlg('Error sending mail (' + IntToStr(Result) + ').', mtError,
[mbOK], 0);
end;
PS: you must add the MAPI unit in USES-clause. To execute this procedure:
ashok111 - Thanks for your code, it looks almost identical to my own (excpet that we can't use the MAPI_DIALOG flag), and works fine for normal situations, just not with the Linux mail server and Outlook express client. I suspect it has something to do with the 'lpFileType' property of the TMapiFileDesc, but I don't know how to set it's properties correctly and all of the examples I have seen just set it to NIL or ignore it completely.
I found this from Microsoft site. It is in VB.
It has a way to send e-mail to the outbox.
Also, the code is very well commented.
Unfortunately it is not in Delphi.
Sub MapiSendMail()
Dim objSession As Object
Dim objMessage As Object
Dim objRecipient As Object
Dim sProfile As String
Dim sSubjPrmpt As String
Dim sTextPrmpt As String
Dim sEmailPrmpt As String
Dim sMsgTitle As String
' Leaving sProfile equal to Null will
' force the user to select which Mapi
' profile to use. To keep from being
' prompted, you must supply a valid
' user profile.
sProfile = ""
sEmailPrmpt = "Enter valid Email Name of message recipient:"
sSubjPrmpt = "Enter the subject line for this message:"
sTextPrmpt = "Enter the text for this message:"
sMsgTitle = "Mapi Macro Example"
' Create the Session Object.
Set objSession = CreateObject("mapi.session
' Log on using the session object.
' Specify a valid profile name if you want to
' avoid the logon dialog box.
objSession.Logon profileName:=sProfile
' Add a new message object to the OutBox.
Set objMessage = objSession.Outbox.Messages
' Set the properties of the message object.
objMessage.Subject = InputBox(sSubjPrmpt, sMsgTitle)
objMessage.Text = InputBox(sTextPrmpt, sMsgTitle)
' Add a recipient object to the objMessage.Recipients collection.
Set objRecipient = objMessage.Recipients.Add
' Set the properties of the recipient object.
objRecipient.Name = InputBox(sEmailPrmpt, sMsgTitle)
objRecipient.Resolve
' Send the message. Setting showDialog to False
' sends the message without displaying the message
' or requiring user intervention. A setting of True
' displays the message and the user must choose
' to Send from within the message dialog.
objMessage.Send showDialog:=False
MsgBox "Message sent successfully!"
' Log off using the session object.
objSession.Logoff
End Sub
Why not just use Mike Shkolnik's free SimpleMAPI control:
http://www.scalabium.com
this will send an email with attachments though outlook express.
======
try this little MAPI example:
uses
Mapi;
function SendEMail(Handle: THandle; Mail: TStrings): Cardinal;
type
TAttachAccessArray = array [0..0] of TMapiFileDesc;
PAttachAccessArray = ^TAttachAccessArray;
var
MapiMessage: TMapiMessage;
Receip: TMapiRecipDesc;
Attachments: PAttachAccessArray;
AttachCount: Integer;
i1: integer;
FileName: string;
dwRet: Cardinal;
MAPI_Session: Cardinal;
WndList: Pointer;
begin
dwRet := MapiLogon(Handle,
PChar(''),
PChar(''),
MAPI_LOGON_UI or MAPI_NEW_SESSION,
0, @MAPI_Session);
if (dwRet <> SUCCESS_SUCCESS) then
begin
MessageBox(Handle,
PChar('Error while trying to send email'),
PChar('Error'),
MB_ICONERROR or MB_OK);
end
else
begin
FillChar(MapiMessage, SizeOf(MapiMessage), #0);
Attachments := nil;
FillChar(Receip, SizeOf(Receip), #0);
if Mail.Values['to'] <> '' then
begin
Receip.ulReserved := 0;
Receip.ulRecipClass := MAPI_TO;
Receip.lpszName := StrNew(PChar(Mail.Values['
Receip.lpszAddress := StrNew(PChar('SMTP:' + Mail.Values['to']));
Receip.ulEIDSize := 0;
MapiMessage.nRecipCount := 1;
MapiMessage.lpRecips := @Receip;
end;
AttachCount := 0;
for i1 := 0 to MaxInt do
begin
if Mail.Values['attachment' + IntToStr(i1)] = '' then
break;
Inc(AttachCount);
end;
if AttachCount > 0 then
begin
GetMem(Attachments, SizeOf(TMapiFileDesc) * AttachCount);
for i1 := 0 to AttachCount - 1 do
begin
FileName := Mail.Values['attachment' + IntToStr(i1)];
Attachments[i1].ulReserved
Attachments[i1].flFlags := 0;
Attachments[i1].nPosition := ULONG($FFFFFFFF);
Attachments[i1].lpszPathNa
Attachments[i1].lpszFileNa
StrNew(PChar(ExtractFileNa
Attachments[i1].lpFileType
end;
MapiMessage.nFileCount := AttachCount;
MapiMessage.lpFiles := @Attachments^;
end;
if Mail.Values['subject'] <> '' then
MapiMessage.lpszSubject := StrNew(PChar(Mail.Values['
if Mail.Values['body'] <> '' then
MapiMessage.lpszNoteText := StrNew(PChar(Mail.Values['
WndList := DisableTaskWindows(0);
try
Result := MapiSendMail(MAPI_Session,
MapiMessage, MAPI_DIALOG, 0);
finally
EnableTaskWindows( WndList );
end;
for i1 := 0 to AttachCount - 1 do
begin
StrDispose(Attachments[i1]
StrDispose(Attachments[i1]
end;
if Assigned(MapiMessage.lpszS
StrDispose(MapiMessage.lps
if Assigned(MapiMessage.lpszN
StrDispose(MapiMessage.lps
if Assigned(Receip.lpszAddres
StrDispose(Receip.lpszAddr
if Assigned(Receip.lpszName) then
StrDispose(Receip.lpszName
MapiLogOff(MAPI_Session, Handle, 0, 0);
end;
end;
procedure TForm1.Button1Click(Sender
var
mail: TStringList;
begin
mail := TStringList.Create;
try
mail.values['to'] := 'Receiver-Email@test.xyz';
mail.values['subject'] := 'Hello';
mail.values['body'] := 'blah';
mail.values['body'] := 'blah';
mail.values['attachment0']
// mail.values['attachment1']
sendEMail(Application.Hand
finally
mail.Free;
end;
end;
====
Hi AndrewNixon,
Dunno if you've already sorted this out yet.
Reading through the problem i see that you mentioned the "winmail.dat" file, the reason you're getting this is the format the mail is being sent in and since you're going through outlook express you might want to change the format within outlook express to plain text.
the winmail.dat file is outlook/outlook express's formatting information for that email and only a small amount of email clients can read it and put the formatting back the way it should be, especially with it going through a linux mail server this will more than likely not come out right on the receiving end. change to plain text (no formatting) and you won't have that problem.
HillGroover
Business Accounts
Answer for Membership
by: calinutzPosted on 2005-03-23 at 00:22:59ID: 13609318
Using SMTP you can have it like this:
ess:='your from address'; :='your name';
='your subject'; s.Clear; s.Add('you r To address'); nts.Clear;
nts.AddStr ings(ListB ox1.Items) ; ar; Strings(Me mo1.Lines) ;
ess:='your from address'; :='your name';
='your subject'; s.Clear; s.Add('you r To Address'); nts.Clear; nts.AddStr ings(ListB ox1.Items) ; ar; Strings(Me mo1.Lines) ;
// the listBox1 contains paths to the files you want to attach to the email
// the Memo1 contains the body of your message
// imeil is the tSMTP component
// I did not understand why not use SMTP?
begin
if imeil.Connected=true then
begin
imeil.Disconnect;
imeil.ClearParameters;
imeil.Host:='yourhost';
imeil.UserID:='yourUserID'
imeil.PostMessage.FromAddr
imeil.PostMessage.FromName
imeil.PostMessage.Subject:
imeil.PostMessage.ToAddres
imeil.PostMessage.ToAddres
imeil.PostMessage.Attachme
imeil.PostMessage.Attachme
imeil.PostMessage.Body.Cle
imeil.PostMessage.Body.Add
end
else
begin
imeil.ClearParameters;
imeil.Host:='yourhost';
imeil.UserID:='yourUserID'
imeil.PostMessage.FromAddr
imeil.PostMessage.FromName
imeil.PostMessage.Subject:
imeil.PostMessage.ToAddres
imeil.PostMessage.ToAddres
imeil.PostMessage.Attachme
imeil.PostMessage.Attachme
imeil.PostMessage.Body.Cle
imeil.PostMessage.Body.Add
imeil.Connect;
end;
imeil.SendMail;
Close;
end;