procedure TMapiControl.SetToAddr(newValue : TStrings); begin FToAdr.Assign(newValue); end; procedure TMapiControl.SetCCAddr(newValue : TStrings); begin FCCAdr.Assign(newValue); end; procedure TMapiControl.SetBCCAddr(newValue : TStrings); begin FBCCAdr.Assign(newValue); end; procedure TMapiControl.SetAttachedFileName(newValue : TStrings); begin FAttachedFileName.Assign(newValue); end; { +< Changes } destructor TMapiControl.Destroy; begin FTOAdr.Free; FCCAdr.Free; FBCCAdr.Free; FAttachedFileName.Free; FDisplayFileName.Free; inherited destroy; end; { Reset the fields for re-use} procedure TMapiControl.Reset; begin FSubject := ''; FMailtext := ''; FFromName := ''; FFromAdress := ''; FTOAdr.Clear; FCCAdr.Clear; FBCCAdr.Clear; FAttachedFileName.Clear; FDisplayFileName.Clear; end; { Send the Mail via the API, this procedure composes and sends the Email } procedure TMapiControl.Sendmail; var MapiMessage: TMapiMessage; MError: Cardinal; Sender: TMapiRecipDesc; PRecip, Recipients: PMapiRecipDesc; PFiles, Attachments: PMapiFileDesc; i: Integer; AppHandle: THandle; begin { First we store the Application Handle, if not the Component might fail to send the Email or your calling Program gets locked up. } AppHandle := Application.Handle; { We need all recipients to alloc the memory } MapiMessage.nRecipCount := FTOAdr.Count + FCCAdr.Count + FBCCAdr.Count; GetMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc)); try with MapiMessage do begin ulReserved := 0; { Setting the Subject: } lpszSubject := PChar(Self.FSubject); { ... the Body: } lpszNoteText := PChar(FMailText); lpszMessageType := nil; lpszDateReceived := nil; lpszConversationID := nil; flFlags := 0; { and the sender: (MAPI_ORIG) } Sender.ulReserved := 0; Sender.ulRecipClass := MAPI_ORIG; Sender.lpszName := PChar(FromName); Sender.lpszAddress := PChar(FromAdress); Sender.ulEIDSize := 0; Sender.lpEntryID := nil; lpOriginator := @Sender; PRecip := Recipients; { We have multiple recipients: (MAPI_TO) and setting up each: } if nRecipCount > 0 then begin for i := 1 to FTOAdr.Count do begin PRecip^.ulReserved := 0; PRecip^.ulRecipClass := MAPI_TO; { lpszName should carry the Name like in the contacts or the adress book, I will take the email adress to keep it short: } PRecip^.lpszName := PChar(FTOAdr.Strings[i - 1]); { If you use this component with Outlook97 or 2000 and not some of Express versions you will have to set 'SMTP:' in front of each (email-) adress. Otherwise Outlook/Mapi will try to handle the Email on itself. Sounds strange, just erease the 'SMTP:', compile, compose a mail and take a look at the resulting email adresses (right click). } PRecip^.lpszAddress := PChar('SMTP:' + FTOAdr.Strings[i - 1]); PRecip^.ulEIDSize := 0; PRecip^.lpEntryID := nil; Inc(PRecip); end; { Same with the carbon copy recipients: (CC, MAPI_CC) } for i := 1 to FCCAdr.Count do begin PRecip^.ulReserved := 0; PRecip^.ulRecipClass := MAPI_CC; PRecip^.lpszName := PChar(FCCAdr.Strings[i - 1]); PRecip^.lpszAddress := PChar('SMTP:' + FCCAdr.Strings[i - 1]); PRecip^.ulEIDSize := 0; PRecip^.lpEntryID := nil; Inc(PRecip); end; { ... and the blind copy recipients: (BCC, MAPI_BCC) } for i := 1 to FBCCAdr.Count do begin PRecip^.ulReserved := 0; PRecip^.ulRecipClass := MAPI_BCC; PRecip^.lpszName := PChar(FBCCAdr.Strings[i - 1]); PRecip^.lpszAddress := PChar('SMTP:' + FBCCAdr.Strings[i - 1]); PRecip^.ulEIDSize := 0; PRecip^.lpEntryID := nil; Inc(PRecip); end; end; lpRecips := Recipients; { Now we process the attachments: } if FAttachedFileName.Count > 0 then begin nFileCount := FAttachedFileName.Count; GetMem(Attachments, MapiMessage.nFileCount * sizeof(TMapiFileDesc)); PFiles := Attachments; { Fist setting up the display names (without path): } FDisplayFileName.Clear; for i := 0 to FAttachedFileName.Count - 1 do FDisplayFileName.Add(ExtractFileName(FAttachedFileName[i])); if nFileCount > 0 then begin { Now we pass the attached file (their paths) to the structure: } for i := 1 to FAttachedFileName.Count do begin { Setting the complete Path } Attachments^.lpszPathName := PChar(FAttachedFileName.Strings[i - 1]); { ... and the displayname: } Attachments^.lpszFileName := PChar(FDisplayFileName.Strings[i - 1]); Attachments^.ulReserved := 0; Attachments^.flFlags := 0; { Position has to be -1, please see the WinApi Help for details. } Attachments^.nPosition := Cardinal(-1); Attachments^.lpFileType := nil; Inc(Attachments); end; end; lpFiles := PFiles; end else begin nFileCount := 0; lpFiles := nil; end; end;
{ Send the Mail, silent or verbose: Verbose means in Express a Mail is composed and shown as setup. In non-Express versions we show the Login-Dialog for a new session and after we have choosen the profile to use, the composed email is shown before sending Silent does currently not work for non-Express version. We have no Session, no Login Dialog so the system refuses to compose a new email. In Express Versions the email is sent in the background. } if FShowDialog then MError := MapiSendMail(0, AppHandle, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI or MAPI_NEW_SESSION, 0) else MError := MapiSendMail(0, AppHandle, MapiMessage, 0, 0); { Now we have to process the error messages. There are some defined in the MAPI unit please take a look at the unit to get familiar with it. I decided to handle USER_ABORT and SUCCESS as special and leave the rest to fire the "new" error event defined at the top (as generic error) Not treated as special: MAPI_E_AMBIGUOUS_RECIPIENT, MAPI_E_ATTACHMENT_NOT_FOUND, MAPI_E_ATTACHMENT_OPEN_FAILURE, MAPI_E_BAD_RECIPTYPE, MAPI_E_FAILURE, MAPI_E_INSUFFICIENT_MEMORY, MAPI_E_LOGIN_FAILURE, MAPI_E_TEXT_TOO_LARGE, MAPI_E_TOO_MANY_FILES, MAPI_E_TOO_MANY_RECIPIENTS, MAPI_E_UNKNOWN_RECIPIENT: } case MError of MAPI_E_USER_ABORT: begin if Assigned(FOnUserAbort) then FOnUserAbort(Self); end; SUCCESS_SUCCESS: begin if Assigned(FOnSuccess) then FOnSuccess(Self); end else begin if Assigned(FOnMapiError) then FOnMapiError(Self, MError); end; end; finally { Finally we do the cleanups, the message should be on its way } FreeMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc)); end; end; { Please treat this as free. If you improve the component I would be glad to get a copy. } end.
delphi自带的例子中有,你可以参考阿, 位置在:delphi安装目录\demos\下
SMTP安全认证的邮件发送程序: c:ehlo hostname s:250-smtp.263.net 250-pipelining 250-size 10240000 250-etrn 250-auth login 250-8bitmime 以上是与邮件服务器连接,即nmsmtp1->connect,以下是连接后的验证: c:auth login s:334VXNlcm5hbWU6(username:) c:b(你的用户名转换成base64码) s:334UGFzc3dvcmQ6(password:) c:x(你的密码转换成base64码) nmsmtp有个transaction方法,在onconnect事件中加入验证过程, nmsmtp1->transaction("auth login"),返回值是334表示通过,可以继续下面的 nmsmtp1->transaction(你的用户名转换成base64码) nmsmtp1->transaction(你的密码转换成base64码) 如果返回235表示验证成功,你就可以发邮件了linzi(林子) (2001-4-19 10:46:00) 得0分 //这是我写的一个演示程序, //窗体上有一个BUTTON控件,一个LABEL控件,一个NMSMTP控件 //带密码险证的邮件发送程序需要BASE64编码,DecodeBase64和 EncodeBase64 //为解码和编码函数 //在263、163和SOHU上都能发送成功 unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Psock, NMsmtp, ComCtrls;type TForm1 = class(TForm) NMSMTP1: TNMSMTP; Button1: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure NMSMTP1Connect(Sender: TObject); procedure NMSMTP1InvalidHost(var Handled: Boolean); procedure NMSMTP1ConnectionFailed(Sender: TObject); procedure NMSMTP1Status(Sender: TComponent; Status: String); procedure NMSMTP1SendStart(Sender: TObject); procedure NMSMTP1Success(Sender: TObject); private { Private declarations } public { Public declarations } end; //BaseTable为BASE64码表 const BaseTable:string='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var Form1: TForm1; AuthSucc:boolean;// 是否需要密码验证 function DecodeBase64(Source:string):string; //解码函数 function FindInTable(CSource:char):integer; // function EncodeBase64(Source:string):string; //编码函数 implementation{$R *.DFM} // function FindInTable(CSource:char):integer; begin result:=Pos(string(CSource),BaseTable)-1; end; //// function DecodeBase64(Source:string):string; var SrcLen,Times,i:integer; x1,x2,x3,x4,xt:byte; begin result:=''; SrcLen:=Length(Source); Times:=SrcLen div 4; for i:=0 to Times-1 do begin x1:=FindInTable(Source[1+i*4]); x2:=FindInTable(Source[2+i*4]); x3:=FindInTable(Source[3+i*4]); x4:=FindInTable(Source[4+i*4]); x1:=x1 shl 2; xt:=x2 shr 4; x1:=x1 or xt; x2:=x2 shl 4; result:=result+chr(x1); if x3= 64 then break; xt:=x3 shr 2; x2:=x2 or xt; x3:=x3 shl 6; result:=result+chr(x2); if x4=64 then break; x3:=x3 or x4; result:=result+chr(x3); end; end; ///// function EncodeBase64(Source:string):string; var Times,LenSrc,i:integer; x1,x2,x3,x4:char; xt:byte; begin result:=''; LenSrc:=length(Source); if LenSrc mod 3 =0 then Times:=LenSrc div 3 else Times:=LenSrc div 3 + 1; for i:=0 to times-1 do begin if LenSrc >= (3+i*3) then begin x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1]; xt:=(ord(Source[1+i*3]) shl 4) and 48; xt:=xt or (ord(Source[2+i*3]) shr 4); x2:=BaseTable[xt+1]; xt:=(Ord(Source[2+i*3]) shl 2) and 60; xt:=xt or (ord(Source[3+i*3]) shr 6); x3:=BaseTable[xt+1]; xt:=(ord(Source[3+i*3]) and 63); x4:=BaseTable[xt+1]; end else if LenSrc>=(2+i*3) then begin x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1]; xt:=(ord(Source[1+i*3]) shl 4) and 48; xt:=xt or (ord(Source[2+i*3]) shr 4); x2:=BaseTable[xt+1]; xt:=(ord(Source[2+i*3]) shl 2) and 60; x3:=BaseTable[xt+1]; x4:='='; end else begin x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1]; xt:=(ord(Source[1+i*3]) shl 4) and 48; x2:=BaseTable[xt+1]; x3:='='; x4:='='; end; result:=result+x1+x2+x3+x4; end; end; ////////// procedure TForm1.Button1Click(Sender: TObject); var MailTo,MailBody:TStringList; begin Nmsmtp1.Host :='smtp.sohu.com'; nmsmtp1.Port :=25; nmsmtp1.UserID :='linbch';//发信人的用户名,必须是真实的 nmsmtp1.ReportLevel :=1; Nmsmtp1.TimeOut :=10000; nmsmtp1.Connect ; ///连接 if AuthSucc=true then ////验证成功 begin MailTo:=TStringList.Create; MailTo.Add('[email protected]'); MailBody.Add('Hello it is a test'); nmsmtp1.PostMessage.FromAddress:='[email protected]'; //发信人的电子邮件地址 nmsmtp1.PostMessage.ToAddress :=MailTo; nmsmtp1.PostMessage.Body:=MailBody; nmsmtp1.PostMessage.Subject :='My test'; Mailto.Clear ; //Mailto.Add('c:\a.txt'); //Mailto.Add('c:\b.txt'); //nmsmtp1.PostMessage.Attachments:=MailTo; 附件 MailTo.Free ; MailBody.Free; nmsmtp1.SendMail; end; end; procedure TForm1.NMSMTP1Connect(Sender: TObject); begin //////连接成功,下面用户认证过程 label1.caption:=nmsmtp1.Status; if nmsmtp1.ReplyNumber = 250 then label1.caption:=nmsmtp1.Transaction('auth login'); //开始认证 if nmsmtp1.ReplyNumber =334 then //返回值为334,让你输入用BASE64编码后的用户名 label1.caption:=nmsmtp1.Transaction('YWFhYWE=');// 用户名aaaaa if nmsmtp1.ReplyNumber =334 then // 返回值为334,让你输入用BASE64编码后的用户密码 label1.caption:=nmsmtp1.Transaction('MTIzNDU2'); //密码为123456 if nmsmtp1.ReplyNumber =235 then begin label1.caption:='successful'; AuthSucc:=true; end; //showmessage(label1.caption); end;procedure TForm1.NMSMTP1InvalidHost(var Handled: Boolean); begin label1.caption :='Invalid Host'; end;procedure TForm1.NMSMTP1ConnectionFailed(Sender: TObject); begin label1.caption :='connect failed'; end;procedure TForm1.NMSMTP1Status(Sender: TComponent; Status: String); begin label1.caption :=nmsmtp1.Status ; end;procedure TForm1.NMSMTP1SendStart(Sender: TObject); begin label1.Caption :='start send'; end;procedure TForm1.NMSMTP1Success(Sender: TObject); begin label1.Caption:='send success!'; end;end.
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type
{ Introducing a new Type of Event to get the Errorcode }
TMapiErrEvent = procedure(Sender: TObject; ErrCode: Integer) of object; TMapiControl = class(TComponent)
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
private
{ Private-Deklarationen }
FSubject: string;
FMailtext: string;
FFromName: string;
FFromAdress: string;
FTOAdr: TStrings;
FCCAdr: TStrings;
FBCCAdr: TStrings;
FAttachedFileName: TStrings;
FDisplayFileName: TStrings;
FShowDialog: Boolean;
FUseAppHandle: Boolean;
{ Error Events: }
FOnUserAbort: TNotifyEvent;
FOnMapiError: TMapiErrEvent;
FOnSuccess: TNotifyEvent;
{ +> Changes by Eugene Mayevski [mailto:[email protected]]}
procedure SetToAddr(newValue : TStrings);
procedure SetCCAddr(newValue : TStrings);
procedure SetBCCAddr(newValue : TStrings);
procedure SetAttachedFileName(newValue : TStrings);
{ +< Changes }
protected
{ Protected-Deklarationen }
public
{ Public-Deklarationen }
ApplicationHandle: THandle;
procedure Sendmail();
procedure Reset();
published
{ Published-Deklarationen }
property Subject: string read FSubject write FSubject;
property Body: string read FMailText write FMailText;
property FromName: string read FFromName write FFromName;
property FromAdress: string read FFromAdress write FFromAdress;
property Recipients: TStrings read FTOAdr write SetTOAddr;
property CopyTo: TStrings read FCCAdr write SetCCAddr;
property BlindCopyTo: TStrings read FBCCAdr write SetBCCAddr;
property AttachedFiles: TStrings read FAttachedFileName write SetAttachedFileName;
property DisplayFileName: TStrings read FDisplayFileName;
property ShowDialog: Boolean read FShowDialog write FShowDialog;
property UseAppHandle: Boolean read FUseAppHandle write FUseAppHandle; { Events: }
property OnUserAbort: TNotifyEvent read FOnUserAbort write FOnUserAbort;
property OnMapiError: TMapiErrEvent read FOnMapiError write FOnMapiError;
property OnSuccess: TNotifyEvent read FOnSuccess write FOnSuccess;
end; procedure Register; implementation uses Mapi; { Register the component: }
procedure Register;
begin
RegisterComponents('expectIT', [TMapiControl]);
end; { TMapiControl } constructor TMapiControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOnUserAbort := nil;
FOnMapiError := nil;
FOnSuccess := nil;
FSubject := '';
FMailtext := '';
FFromName := '';
FFromAdress := '';
FTOAdr := TStringList.Create;
FCCAdr := TStringList.Create;
FBCCAdr := TStringList.Create;
FAttachedFileName := TStringList.Create;
FDisplayFileName := TStringList.Create;
FShowDialog := False;
ApplicationHandle := Application.Handle;
end;
begin
FToAdr.Assign(newValue);
end; procedure TMapiControl.SetCCAddr(newValue : TStrings);
begin
FCCAdr.Assign(newValue);
end; procedure TMapiControl.SetBCCAddr(newValue : TStrings);
begin
FBCCAdr.Assign(newValue);
end; procedure TMapiControl.SetAttachedFileName(newValue : TStrings);
begin
FAttachedFileName.Assign(newValue);
end;
{ +< Changes } destructor TMapiControl.Destroy;
begin
FTOAdr.Free;
FCCAdr.Free;
FBCCAdr.Free;
FAttachedFileName.Free;
FDisplayFileName.Free;
inherited destroy;
end; { Reset the fields for re-use}
procedure TMapiControl.Reset;
begin
FSubject := '';
FMailtext := '';
FFromName := '';
FFromAdress := '';
FTOAdr.Clear;
FCCAdr.Clear;
FBCCAdr.Clear;
FAttachedFileName.Clear;
FDisplayFileName.Clear;
end; { Send the Mail via the API, this procedure composes and sends
the Email }
procedure TMapiControl.Sendmail;
var
MapiMessage: TMapiMessage;
MError: Cardinal;
Sender: TMapiRecipDesc;
PRecip, Recipients: PMapiRecipDesc;
PFiles, Attachments: PMapiFileDesc;
i: Integer;
AppHandle: THandle;
begin
{ First we store the Application Handle, if not
the Component might fail to send the Email or
your calling Program gets locked up. }
AppHandle := Application.Handle; { We need all recipients to alloc the memory }
MapiMessage.nRecipCount := FTOAdr.Count + FCCAdr.Count + FBCCAdr.Count;
GetMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc)); try
with MapiMessage do
begin
ulReserved := 0;
{ Setting the Subject: }
lpszSubject := PChar(Self.FSubject); { ... the Body: }
lpszNoteText := PChar(FMailText); lpszMessageType := nil;
lpszDateReceived := nil;
lpszConversationID := nil;
flFlags := 0; { and the sender: (MAPI_ORIG) }
Sender.ulReserved := 0;
Sender.ulRecipClass := MAPI_ORIG;
Sender.lpszName := PChar(FromName);
Sender.lpszAddress := PChar(FromAdress);
Sender.ulEIDSize := 0;
Sender.lpEntryID := nil;
lpOriginator := @Sender; PRecip := Recipients; { We have multiple recipients: (MAPI_TO)
and setting up each: }
if nRecipCount > 0 then
begin
for i := 1 to FTOAdr.Count do
begin
PRecip^.ulReserved := 0;
PRecip^.ulRecipClass := MAPI_TO;
{ lpszName should carry the Name like in the
contacts or the adress book, I will take the
email adress to keep it short: }
PRecip^.lpszName := PChar(FTOAdr.Strings[i - 1]);
{ If you use this component with Outlook97 or 2000
and not some of Express versions you will have to set
'SMTP:' in front of each (email-) adress. Otherwise
Outlook/Mapi will try to handle the Email on itself.
Sounds strange, just erease the 'SMTP:', compile, compose
a mail and take a look at the resulting email adresses
(right click).
}
PRecip^.lpszAddress := PChar('SMTP:' + FTOAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end; { Same with the carbon copy recipients: (CC, MAPI_CC) }
for i := 1 to FCCAdr.Count do
begin
PRecip^.ulReserved := 0;
PRecip^.ulRecipClass := MAPI_CC;
PRecip^.lpszName := PChar(FCCAdr.Strings[i - 1]);
PRecip^.lpszAddress := PChar('SMTP:' + FCCAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end; { ... and the blind copy recipients: (BCC, MAPI_BCC) }
for i := 1 to FBCCAdr.Count do
begin
PRecip^.ulReserved := 0;
PRecip^.ulRecipClass := MAPI_BCC;
PRecip^.lpszName := PChar(FBCCAdr.Strings[i - 1]);
PRecip^.lpszAddress := PChar('SMTP:' + FBCCAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end;
end;
lpRecips := Recipients; { Now we process the attachments: } if FAttachedFileName.Count > 0 then
begin
nFileCount := FAttachedFileName.Count;
GetMem(Attachments, MapiMessage.nFileCount * sizeof(TMapiFileDesc)); PFiles := Attachments; { Fist setting up the display names (without path): }
FDisplayFileName.Clear;
for i := 0 to FAttachedFileName.Count - 1 do
FDisplayFileName.Add(ExtractFileName(FAttachedFileName[i])); if nFileCount > 0 then
begin
{ Now we pass the attached file (their paths) to the
structure: }
for i := 1 to FAttachedFileName.Count do
begin
{ Setting the complete Path }
Attachments^.lpszPathName := PChar(FAttachedFileName.Strings[i - 1]);
{ ... and the displayname: }
Attachments^.lpszFileName := PChar(FDisplayFileName.Strings[i - 1]);
Attachments^.ulReserved := 0;
Attachments^.flFlags := 0;
{ Position has to be -1, please see the WinApi Help
for details. }
Attachments^.nPosition := Cardinal(-1);
Attachments^.lpFileType := nil;
Inc(Attachments);
end;
end;
lpFiles := PFiles;
end
else
begin
nFileCount := 0;
lpFiles := nil;
end;
end;
Verbose means in Express a Mail is composed and shown as setup.
In non-Express versions we show the Login-Dialog for a new
session and after we have choosen the profile to use, the
composed email is shown before sending Silent does currently not work for non-Express version. We have
no Session, no Login Dialog so the system refuses to compose a
new email. In Express Versions the email is sent in the
background.
}
if FShowDialog then
MError := MapiSendMail(0, AppHandle, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI or MAPI_NEW_SESSION, 0)
else
MError := MapiSendMail(0, AppHandle, MapiMessage, 0, 0); { Now we have to process the error messages. There are some
defined in the MAPI unit please take a look at the unit to get
familiar with it.
I decided to handle USER_ABORT and SUCCESS as special and leave
the rest to fire the "new" error event defined at the top (as
generic error) Not treated as special:
MAPI_E_AMBIGUOUS_RECIPIENT,
MAPI_E_ATTACHMENT_NOT_FOUND,
MAPI_E_ATTACHMENT_OPEN_FAILURE,
MAPI_E_BAD_RECIPTYPE,
MAPI_E_FAILURE,
MAPI_E_INSUFFICIENT_MEMORY,
MAPI_E_LOGIN_FAILURE,
MAPI_E_TEXT_TOO_LARGE,
MAPI_E_TOO_MANY_FILES,
MAPI_E_TOO_MANY_RECIPIENTS,
MAPI_E_UNKNOWN_RECIPIENT:
} case MError of
MAPI_E_USER_ABORT:
begin
if Assigned(FOnUserAbort) then
FOnUserAbort(Self);
end;
SUCCESS_SUCCESS:
begin
if Assigned(FOnSuccess) then
FOnSuccess(Self);
end
else begin
if Assigned(FOnMapiError) then
FOnMapiError(Self, MError);
end; end;
finally
{ Finally we do the cleanups, the message should be on its way }
FreeMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc));
end;
end; {
Please treat this as free. If you improve the component
I would be glad to get a copy.
} end.
位置在:delphi安装目录\demos\下
SMTP安全认证的邮件发送程序:
c:ehlo hostname
s:250-smtp.263.net
250-pipelining
250-size 10240000
250-etrn
250-auth login
250-8bitmime
以上是与邮件服务器连接,即nmsmtp1->connect,以下是连接后的验证:
c:auth login
s:334VXNlcm5hbWU6(username:)
c:b(你的用户名转换成base64码)
s:334UGFzc3dvcmQ6(password:)
c:x(你的密码转换成base64码)
nmsmtp有个transaction方法,在onconnect事件中加入验证过程,
nmsmtp1->transaction("auth login"),返回值是334表示通过,可以继续下面的
nmsmtp1->transaction(你的用户名转换成base64码)
nmsmtp1->transaction(你的密码转换成base64码)
如果返回235表示验证成功,你就可以发邮件了linzi(林子) (2001-4-19 10:46:00) 得0分
//这是我写的一个演示程序,
//窗体上有一个BUTTON控件,一个LABEL控件,一个NMSMTP控件
//带密码险证的邮件发送程序需要BASE64编码,DecodeBase64和 EncodeBase64
//为解码和编码函数
//在263、163和SOHU上都能发送成功
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Psock, NMsmtp, ComCtrls;type
TForm1 = class(TForm)
NMSMTP1: TNMSMTP;
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure NMSMTP1Connect(Sender: TObject);
procedure NMSMTP1InvalidHost(var Handled: Boolean);
procedure NMSMTP1ConnectionFailed(Sender: TObject);
procedure NMSMTP1Status(Sender: TComponent; Status: String);
procedure NMSMTP1SendStart(Sender: TObject);
procedure NMSMTP1Success(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//BaseTable为BASE64码表
const BaseTable:string='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var
Form1: TForm1;
AuthSucc:boolean;// 是否需要密码验证
function DecodeBase64(Source:string):string; //解码函数
function FindInTable(CSource:char):integer; //
function EncodeBase64(Source:string):string; //编码函数
implementation{$R *.DFM}
//
function FindInTable(CSource:char):integer;
begin
result:=Pos(string(CSource),BaseTable)-1;
end;
////
function DecodeBase64(Source:string):string;
var
SrcLen,Times,i:integer;
x1,x2,x3,x4,xt:byte;
begin
result:='';
SrcLen:=Length(Source);
Times:=SrcLen div 4;
for i:=0 to Times-1 do
begin
x1:=FindInTable(Source[1+i*4]);
x2:=FindInTable(Source[2+i*4]);
x3:=FindInTable(Source[3+i*4]);
x4:=FindInTable(Source[4+i*4]);
x1:=x1 shl 2;
xt:=x2 shr 4;
x1:=x1 or xt;
x2:=x2 shl 4;
result:=result+chr(x1);
if x3= 64 then break;
xt:=x3 shr 2;
x2:=x2 or xt;
x3:=x3 shl 6;
result:=result+chr(x2);
if x4=64 then break;
x3:=x3 or x4;
result:=result+chr(x3);
end;
end;
/////
function EncodeBase64(Source:string):string;
var
Times,LenSrc,i:integer;
x1,x2,x3,x4:char;
xt:byte;
begin
result:='';
LenSrc:=length(Source);
if LenSrc mod 3 =0 then Times:=LenSrc div 3
else Times:=LenSrc div 3 + 1;
for i:=0 to times-1 do
begin
if LenSrc >= (3+i*3) then
begin
x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
xt:=(ord(Source[1+i*3]) shl 4) and 48;
xt:=xt or (ord(Source[2+i*3]) shr 4);
x2:=BaseTable[xt+1];
xt:=(Ord(Source[2+i*3]) shl 2) and 60;
xt:=xt or (ord(Source[3+i*3]) shr 6);
x3:=BaseTable[xt+1];
xt:=(ord(Source[3+i*3]) and 63);
x4:=BaseTable[xt+1];
end
else if LenSrc>=(2+i*3) then
begin
x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
xt:=(ord(Source[1+i*3]) shl 4) and 48;
xt:=xt or (ord(Source[2+i*3]) shr 4);
x2:=BaseTable[xt+1];
xt:=(ord(Source[2+i*3]) shl 2) and 60;
x3:=BaseTable[xt+1];
x4:='=';
end else
begin
x1:=BaseTable[(ord(Source[1+i*3]) shr 2)+1];
xt:=(ord(Source[1+i*3]) shl 4) and 48;
x2:=BaseTable[xt+1];
x3:='=';
x4:='=';
end;
result:=result+x1+x2+x3+x4;
end;
end;
//////////
procedure TForm1.Button1Click(Sender: TObject);
var MailTo,MailBody:TStringList;
begin
Nmsmtp1.Host :='smtp.sohu.com';
nmsmtp1.Port :=25;
nmsmtp1.UserID :='linbch';//发信人的用户名,必须是真实的
nmsmtp1.ReportLevel :=1;
Nmsmtp1.TimeOut :=10000;
nmsmtp1.Connect ; ///连接
if AuthSucc=true then ////验证成功
begin
MailTo:=TStringList.Create;
MailTo.Add('[email protected]');
MailBody.Add('Hello it is a test');
nmsmtp1.PostMessage.FromAddress:='[email protected]'; //发信人的电子邮件地址
nmsmtp1.PostMessage.ToAddress :=MailTo;
nmsmtp1.PostMessage.Body:=MailBody;
nmsmtp1.PostMessage.Subject :='My test';
Mailto.Clear ;
//Mailto.Add('c:\a.txt');
//Mailto.Add('c:\b.txt');
//nmsmtp1.PostMessage.Attachments:=MailTo; 附件
MailTo.Free ;
MailBody.Free;
nmsmtp1.SendMail;
end;
end;
procedure TForm1.NMSMTP1Connect(Sender: TObject);
begin
//////连接成功,下面用户认证过程
label1.caption:=nmsmtp1.Status;
if nmsmtp1.ReplyNumber = 250 then
label1.caption:=nmsmtp1.Transaction('auth login'); //开始认证
if nmsmtp1.ReplyNumber =334 then //返回值为334,让你输入用BASE64编码后的用户名
label1.caption:=nmsmtp1.Transaction('YWFhYWE=');// 用户名aaaaa
if nmsmtp1.ReplyNumber =334 then // 返回值为334,让你输入用BASE64编码后的用户密码
label1.caption:=nmsmtp1.Transaction('MTIzNDU2'); //密码为123456
if nmsmtp1.ReplyNumber =235 then
begin
label1.caption:='successful';
AuthSucc:=true;
end;
//showmessage(label1.caption);
end;procedure TForm1.NMSMTP1InvalidHost(var Handled: Boolean);
begin
label1.caption :='Invalid Host';
end;procedure TForm1.NMSMTP1ConnectionFailed(Sender: TObject);
begin
label1.caption :='connect failed';
end;procedure TForm1.NMSMTP1Status(Sender: TComponent; Status: String);
begin
label1.caption :=nmsmtp1.Status ;
end;procedure TForm1.NMSMTP1SendStart(Sender: TObject);
begin
label1.Caption :='start send';
end;procedure TForm1.NMSMTP1Success(Sender: TObject);
begin
label1.Caption:='send success!';
end;end.
这是个例子http://www.csdn.net/cnshare/soft/12/12399.shtm
恳请指教!
确实不错的。
推荐