不用安全认证只用如下即可实现:
if nmsmtp1.Connected then
nmsmtp1.Disconnect
else
begin
nmsmtp1.Host:=trim(DataModule1.ADOQuery42.fieldbyname('kty').asstring);
nmsmtp1.UserID:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
nmsmtp1.
try
nmsmtp1.Connect;
statusbar1.panels[0].text:='Á¬½ÓÓʼþ·þÎñÆ÷³É¹¦£¡';
except
statusbar1.panels[0].text:='Á¬½ÓÓʼþ·þÎñÆ÷ʧ°Ü!Çë¼ì²éÄãµÄÓʼþ·þÎñÆ÷ÊÇ·ñÉèÖÃÕýÈ·,»òÍøÂçÊÇ·ñÒÑÁ¬Í¨.';
end;
end; //连接.if nmsmtp1.Connected then
begin
NMSMTP1.EncodeType:= uuMime;
NMSMTP1.PostMessage.FromAddress:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
NMSMTP1.PostMessage.ToAddress.Text:=edit4.text;
NMSMTP1.PostMessage.Body.Text:=Memo1.Text;
NMSMTP1.PostMessage.Attachments.Text:=ListBox2.Items.Text;
NMSMTP1.PostMessage.Subject:=Edit5.Text;
NMSMTP1.SendMail;
end
else
statusbar1.panels[0].text:='¾¯¸æ£ºµ±Ç°Ã»Á¬ÉÏÈκηþÎñÆ÷!';
//发送.如要全安认证又如何实现呢? nmsmtp又没有nmpop的password属性.
if nmsmtp1.Connected then
nmsmtp1.Disconnect
else
begin
nmsmtp1.Host:=trim(DataModule1.ADOQuery42.fieldbyname('kty').asstring);
nmsmtp1.UserID:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
nmsmtp1.
try
nmsmtp1.Connect;
statusbar1.panels[0].text:='Á¬½ÓÓʼþ·þÎñÆ÷³É¹¦£¡';
except
statusbar1.panels[0].text:='Á¬½ÓÓʼþ·þÎñÆ÷ʧ°Ü!Çë¼ì²éÄãµÄÓʼþ·þÎñÆ÷ÊÇ·ñÉèÖÃÕýÈ·,»òÍøÂçÊÇ·ñÒÑÁ¬Í¨.';
end;
end; //连接.if nmsmtp1.Connected then
begin
NMSMTP1.EncodeType:= uuMime;
NMSMTP1.PostMessage.FromAddress:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
NMSMTP1.PostMessage.ToAddress.Text:=edit4.text;
NMSMTP1.PostMessage.Body.Text:=Memo1.Text;
NMSMTP1.PostMessage.Attachments.Text:=ListBox2.Items.Text;
NMSMTP1.PostMessage.Subject:=Edit5.Text;
NMSMTP1.SendMail;
end
else
statusbar1.panels[0].text:='¾¯¸æ£ºµ±Ç°Ã»Á¬ÉÏÈκηþÎñÆ÷!';
//发送.如要全安认证又如何实现呢? nmsmtp又没有nmpop的password属性.
解决方案 »
- delphi开发asp的com组件,怎么输出?
- 自己开发了一个CRM,可以免费使用及分发,希望对有需要朋友有帮助!
- 定义这个接口实现类,错误在那里呢?
- 怎么让DBGrid的某列的数据显示为红色
- 谁会删除 TComboBoxEx 中的 ItemEx ?
- 一晚无睡,能否spcomm控制接在串口上的手机?如果能,他是如何传送AT命令的?
- 在TORBO PASCAL6.0下如何把图形驱动静态连接到程序中?
- 初学!请指教TDBNavigator构件后面几个按钮为何不可用?
- 高手请帮忙,在线等待.为何我提交数据时,总是提示"无法为更新行集定位:一些值可能已在最后读取后改变".?急!
- 请教TFileStream.Seek函数为啥定位总不正确。
- 郁闷!一个MM猛批我的程序,如何提高系统稳定性啊!(心情不好散分。。。。)
- Activform在调试过程中不能自动更新?
if nmsmtp1.Connected then
nmsmtp1.Disconnect
else
begin
nmsmtp1.Host:=trim(DataModule1.ADOQuery42.fieldbyname('kty').asstring);
nmsmtp1.UserID:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
try
nmsmtp1.Connect;
statusbar1.panels[0].text:='连接成功.;';
except
statusbar1.panels[0].text:='连接失败;¨.';
end;
end; //连接.if nmsmtp1.Connected then
begin
NMSMTP1.EncodeType:= uuMime;
NMSMTP1.PostMessage.FromAddress:=trim(DataModule1.ADOQuery42.fieldbyname('jsy').asstring);
NMSMTP1.PostMessage.ToAddress.Text:=edit4.text;
NMSMTP1.PostMessage.Body.Text:=Memo1.Text;
NMSMTP1.PostMessage.Attachments.Text:=ListBox2.Items.Text;
NMSMTP1.PostMessage.Subject:=Edit5.Text;
NMSMTP1.SendMail;
end
else
statusbar1.panels[0].text:='send fail!';
//发送.如要全安认证又如何实现呢? nmsmtp又没有nmpop的password属性.
sorry.上面写错了.
例如,虽然TNMSMTP不直接支持“SMTP服务器认证功能”,但是,可以利用TNMSMTP的Connect事件和继承自TPowersock的Transaction方法,实现SMTP服务器认证。其原理在于,Connect事件发生在TNMSMTP与服务器连接成功之时,此时,使用Transaction方法发出SMTP服务器认证所规定的“AUTH LOGIN”命令,并输入经过BASE64编码后的用户名和密码,可以实现认证。因此,本程序实现了SMTP服务器认证。另外,TNMSMTP的SendStart事件在邮件发送开始时触发,在该事件中,可以通过修改TNMSMTP的FinalHeader属性值,实现修改电子邮件的邮件头信息。
4.2.2电子邮件发送程序实现
由于现在的SMTP的服务器都需要认证,而认证要发送的用户名和密码需要对用户名和密码进行BASE64编码,所以在这里我编了一个函数
function EncodeString(Decoded:string):String;
这个函数这要用来对认证要发送的密码进行BASE64编码,BASE64的编码程序原理在前面讲过了,在这里不在进行说明。
本程序使用了自定义消息机制的消息传送机制。由于发送邮件也需要在登陆邮件服务器在后才进行操作,因此该消息在登陆服务器之后才进行操作,因此该消息在登陆服务器之后发送给主程序,触发自己实现的消息响音函数进行处理。
使用者在编辑完邮件之后就可以点击“发送邮件”按钮进行发送邮件了。在发送之前,首先必须确定使用者是否已经填写好所有的必须信息,特别是收信人的信息,所有的信息都完备之后开始连接邮件服务器。“发送邮件”按钮的OnClick事件实现如下:
procedure TForm1.ToolButton3Click(Sender: TObject);begin
{验证用户输入信息}
if txtTo.Text='' then
begin
ShowMessage('请输入收信人!');
Exit;
end;
{设置SMTP服务器信息}
NMSMTP1.Host := form2.smtpsever ;
NMSMTP1.Port := form2.smtpport ;
NMSMTP1.UserID:=form2.smtpUserName ;
{报告当前状态}
StatusBar1.SimpleText:='Connecting...';
StatusBar1.Update;
{连接服务器}
NMSMTP1.Connect;
end;
如果连接邮件服务器成功,NMSMTP组建就会触发OnConnect事件,在该事件处理函数需要向主程序发送自定义消息并发送认证需要的密码,具体代码如下:
procedure TForm1.NMSMTP1Connect(Sender: TObject);
var
strUserName,strPassword:string;
begin {对用户名和密码进行Base64编码}
strUserName:=EncodeString(form2.smtpUserName);
strPassword:=EncodeString(form2.smtpPassword);
nmsmtp1.Transaction('auth login'); { 进行认证,输入编码后的用户名、密码}
nmsmtp1.Transaction(strUserName);
nmsmtp1.Transaction(strPassword);
{报告状态}
StatusBar1.SimpleText:='Connected';
StatusBar1.Update;
{发送自定义消息}
SendMessage(Handle,WM_LOGIN,0,0);
end;如果连接失败,就需要及时通知使用者,代码如下:
procedure TForm1.NMSMTP1ConnectionFailed(Sender: TObject);
begin
ShowMessage('Connection Failed');
end;
在定义消息到主窗体之后,就会执行对应的自定义消息函数,在该函数中进行邮件发送的主要工作,包括发送之前的邮件信息填写。在发送完成之后还需要及时切断和邮件服务器的对话,具体代码如下:
procedure TForm1.WMLOGIN(var Msg: TWM);
begin
//Send mail
{填写邮件内容}
NMSMTP1.SubType:=mthtml;
//write receiver info
NMSMTP1.PostMessage.FromAddress := form2.mailname ;
NMSMTP1.PostMessage.FromName := form2.smtpUserName ;
NMSMTP1.PostMessage.Subject := txtSubject.Text;
NMSMTP1.PostMessage.ToAddress.Add(txtTo.Text);
NMSMTP1.PostMessage.Attachments.AddStrings(Listbox1.Items);
NMSMTP1.PostMessage.Body.Assign(memContents.Lines);
{发送邮件}
NMSMTP1.SendMail;
{断开连接}
NMSMTP1.Disconnect;
end;
如果断开连接操作成功,触发OnDisconnect事件,可以利用这个事件提示使用者邮件已经发送成功,具体代码如下:
procedure TForm1.NMSMTP1Disconnect(Sender: TObject);
begin
If StatusBar1 <> nil then
StatusBar1.SimpleText := 'Disconnected from server';
end;在整个的过程中,还需要以下一个比较重要的信息。
如果域名解析成功触发如下事件:
procedure TForm1.NMSMTP1HostResolved(Sender: TComponent);
begin
StatusBar1.SimpleText := 'HostResolved';
end;如果检测域名失败触发如下事件:
procedure TForm1.NMSMTP1InvalidHost(var Handled: Boolean);
begin
StatusBar1.SimpleText := 'InvalidHost';
end;在邮件即将开始发送之前会出发以下事件:
procedure TForm1.NMSMTP1SendStart(Sender: TObject);
begin
StatusBar1.SimpleText := 'SendStart';
end;在操作成功的时候会触发OnSuccess事件:
procedure TForm1.NMSMTP1Success(Sender: TObject);
begin
StatusBar1.SimpleText := 'Success';
end;整个程序还需要有邮件附件的增删功能。用户可以使用“添加附件”按钮来添加附件,该按钮的OnClick事件的程序段如下:
procedure TForm1.ToolButton4Click(Sender: TObject);
begin
if OpenDialog1.Execute then
ListBox1.Items.Add(
OpenDialog1.FileName);
end;用户在ListBox组件上可以选择需要删除的附件,使用键盘的“Delete”键删除,代码实现如下:
procedure TForm1.ListBox1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
idex:integer;
begin
//valid check
if ListBox1.ItemIndex=-1 then
exit;
//key detect
if Key<> VK_DELETE then
exit;
idex:=listbox1.ItemIndex;
listbox1.Items.Delete(idex);
end;
有时间吗,我请你吃饭.
到底如何实现呵?
{对参数TMemoryStrema中的字节流进行Base64编码,编码后的结果
保存在Encoded中,函数返回编码长度}
function TForm1.EncodeBASE64(Encoded: TMemoryStream ; Decoded: TMemoryStream): Integer;
const
_Code64: String[64] =
('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/');
var
I: LongInt;
B: array[0..2279] of Byte;
J, K, L, M, Quads: Integer;
Stream: string[76];
EncLine: String;
begin Encoded.Clear; Stream := '';
Quads := 0; {为提高效率,每2280字节流为一组进行编码}
J := Decoded.Size div 2280; Decoded.Position := 0; {对前J*2280个字节流进行编码}
for I := 1 to J do
begin
Decoded.Read(B, 2280); for M := 0 to 39 do
begin
for K := 0 to 18 do
begin
L:= 57*M + 3*K; Stream[Quads+1] := _Code64[(B[L] div 4)+1];
Stream[Quads+2] := _Code64[(B[L] mod 4)*16 + (B[L+1] div 16)+1];
Stream[Quads+3] := _Code64[(B[L+1] mod 16)*4 + (B[L+2] div 64)+1];
Stream[Quads+4] := _Code64[B[L+2] mod 64+1]; Inc(Quads, 4); if Quads = 76 then
begin
Stream[0] := #76;
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
Quads := 0;
end;
end;
end;
end; {对以2280为模的余数字节流进行编码}
J := (Decoded.Size mod 2280) div 3; for I := 1 to J do
begin
Decoded.Read(B, 3); Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + (B[1] div 16)+1];
Stream[Quads+3] := _Code64[(B[1] mod 16)*4 + (B[2] div 64)+1];
Stream[Quads+4] := _Code64[B[2] mod 64+1]; Inc(Quads, 4); {每行76个字符}
if Quads = 76 then
begin
Stream[0] := #76;
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
Quads := 0;
end;
end;
{“=”补位}
if (Decoded.Size mod 3) = 2 then
begin
Decoded.Read(B, 2); Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + (B[1] div 16)+1];
Stream[Quads+3] := _Code64[(B[1] mod 16)*4 + 1];
Stream[Quads+4] := '='; Inc(Quads, 4);
end; if (Decoded.Size mod 3) = 1 then
begin
Decoded.Read(B, 1); Stream[Quads+1] := _Code64[(B[0] div 4)+1];
Stream[Quads+2] := _Code64[(B[0] mod 4)*16 + 1];
Stream[Quads+3] := '=';
Stream[Quads+4] := '=';
Inc(Quads, 4);
end; Stream[0] := Chr(Quads); if Quads > 0 then
begin
EncLine := Stream+#13#10;
Encoded.Write(EncLine[1], Length(EncLine));
end; Result := Encoded.Size;
end;{对参数Decoded字符串进行Base64编码,返回编码后的字符串}
function TForm1.EncodeString(Decoded:string):String;
var
mmTemp,mmDecoded:TMemoryStream;
strTemp:TStrings;
begin
mmTemp := TMemoryStream.Create;
mmDecoded:=TMemoryStream.Create;
strTemp:=TStringList.Create; strTemp.Add(Decoded);
strTemp.SaveToStream(mmTemp);
mmTemp.Position := 0; {剔除mmTemp从strTemp中带来的字符#13#10}
mmDecoded.CopyFrom(mmTemp,mmTemp.Size-2); {对mmDecoded进行Base64编码,由mmTemp返回编码后的结果}
EncodeBASE64(mmTemp,mmDecoded); {获得Base64编码后的字符串}
mmTemp.Position:=0;
strTemp.LoadFromStream(mmTemp); {返回结果必须从strTemp[0]中获得,如果使用strTemp.Text会
带来不必要的字符#13#10}
Result:=strTemp[0];
end;