socket 发邮件的问题(100)

  • 主题发起人 主题发起人 anni9977
  • 开始时间 开始时间
A

anni9977

Unregistered / Unconfirmed
GUEST, unregistred user!
在网上找了个发邮件的单元,现在遇到个问题就是用126和163的邮箱发没问题,但是用我们自己的邮件服务器发发不出去,我们的服务器是直接指IP的没有域名,哪位大侠知道怎么回事啊,在线等,现把代码粘上unit uMail;interfaceuses WinSock, Windows, SysUtils, Classes, Math;const CRLF :string = #13 + #10;type TMail = class private FFromAddr : string; //真正发送邮件的邮箱 FShowFromAddr : string;//显示的发件人 FToAddr : string; //发送给谁 FCCAddr : string; //抄送 FBCCAddr : string; //暗送 FSubject : string; //标题 FBody : string; //正文 FErrMsg : string; //错误信息 FHost : string; //发送邮件服务器 FAttaches : TStrings; //附件列表 FSendData : TStrings; //发送的附加信息 FPassword : string; //发送邮箱的密码 FBodybs:Integer;//0为普通邮件,1为html邮件 function chunklenSplit(Value : string): string; function GetSendData: string; protected procedure InitSendData; public constructor Create; destructor Destory; property Host : string read FHost write FHost; property FromAddr : string read FFromAddr write FFromAddr; property ShowFromAddr : string read FShowFromAddr write FShowFromAddr; property ToAddr : string read FToAddr write FToAddr; property CCAddr : string read FCCAddr write FCCAddr; property BCCAddr : string read FBCCAddr write FBCCAddr; property Subject : string read FSubject write FSubject; property Body : string read FBody write FBody; property Attaches : TStrings read FAttaches write FAttaches; property ErrMsg : string read FErrMsg; property SendData : string read GetSendData; property Password : string read FPassword write FPassword; property bodybs:Integer read FBodybs write FBodybs; function Send : boolean; end;implementationuses Base64;{ TMail }function TMail.chunklenSplit(Value: string): string;var I,len : integer;begin Result := ''; for i := 0 to floor(Length(Value) / 76) do begin if i * 76 + 77 > Length(Value) then len := Length(Value) - (i-1) * 76 + 1 else len := 76; Result := Result + Copy(Value,i * 76 + 1,len) + CRLF; end; end;constructor TMail.Create;var WSData: TWSAData;begin WSAstartup(1, WSData); FAttaches := TStringList.Create; FSendData := TStringList.Create;end;destructor TMail.Destory;begin FAttaches.Free; FSendData.Free; WSACleanup;end;function TMail.GetSendData: string;begin Result := FSendData.Text;end;procedure TMail.InitSendData;var guid : TGUID; fs : TFileStream; fbuf : array of byte; boundary,fn,sbuf : string; i ,j: integer; tmpstrl:TStringList;begin FSendData.Clear; CreateGUID(guid); boundary := Copy(GuidToString(Guid),2,Length(GuidToString(Guid))-2); FSendData.Add('To: "'+FToAddr+'"'); FSendData.Add('reply-to: "'+FShowFromAddr+'" <'+FShowFromAddr+'>'); //回复地址 if FCCAddr<>'' then FSendData.Add('Cc: "'+FCCAddr+'"'); if FBCCAddr<>'' then FSendData.Add('BCc: "'+FBCCAddr+'"'); FSendData.Add('Subject:'+ FSubject); FSendData.Add('MIME-Version: 1.0'); FSendData.Add('Content-Type: multipart/mixed;'); FSendData.Add(#9 + 'boundary="=='+boundary+'"' + CRLF); FSendData.Add('This is a MIME encoded message.' + CRLF); FSendData.Add('--=='+boundary); //FSendData.Add('Content-Type: text/plain;'); if FBodybs=0 then FSendData.Add('Content-Type: text/plain;') else FSendData.Add('Content-Type: text/html;'); FSendData.Add(#9+'charset="gb2312"'); //FSendData.Add(#9+'charset="big5"'); FSendData.Add('Content-Transfer-Encoding: base64'+ CRLF); if FBodybs=0 then FSendData.Add(Base64EncodeStr(FBody) + CRLF) else begin tmpstrl:=TStringList.Create; tmpstrl.LoadFromFile(fbody); for j:=0 to tmpstrl.Count-1 do tmpstrl.Strings[j]:=Base64EncodeStr(tmpstrl.Strings[j]); FSendData.AddStrings(tmpstrl); tmpstrl.Free; end; //FSendData.Add(EncodeBASE64(FBody) + CRLF); for i := 0 to FAttaches.Count - 1 do begin if FileExists(FAttaches) then begin fn := ExtractFileName(FAttaches); FSendData.Add('--==' + boundary); FSendData.Add('Content-Type: application/octet-stream;'); FSendData.Add(#9 + 'name="'+fn+'"'); FSendData.Add('Content-Transfer-Encoding: base64'); FSendData.Add('Content-Disposition: attachment;'); FSendData.Add(#9+'filename="'+fn+'"' + CRLF); fs := TFileStream.Create(FAttaches, fmShareDenyNone); try SetLength(fbuf,fs.Size); SetLength(sbuf, ((fs.Size+2) div 3)*4); fs.ReadBuffer(fbuf[0], fs.Size); Base64Encode(fbuf,@sbuf[1],fs.Size); sbuf := chunklenSplit(sbuf); FSendData.Add(sbuf); finally fs.Free; end; end; end; FSendData.Add('--=='+boundary+'--' + CRLF + CRLF + '.');end;function TMail.Send: boolean;var sock : TSocket; mhost : PHostEnt; maddr : TSockAddrIn; rbuf : array[0..255] of char; sbuf,useri : string; tmpip:DWORD;begin Result := true; sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); try if sock = INVALID_SOCKET then begin Result := false; FErrMsg := '创建Socket失败!'; Exit; end; {如是ip则用 tmpip:=inet_addr(PChar(FHost)); mhost:=GetHostByAddr(@tmpip,SizeOf(tmpip), AF_INet); } mhost := gethostbyname(pchar(FHost)); if mhost = nil then begin Result := false; FErrMsg := '获取主机地址失败!'; Exit; end; maddr.sin_family := AF_INET; maddr.sin_port := htons(25); // maddr.sin_port := htons(8012); inet_addr(P Char(IPAddr)); maddr.sin_addr.S_addr := Longint(PLongint(mhost^.h_addr_list^)^); //maddr.sin_addr.S_addr := inet_addr(PChar(fhost)); if connect(sock,maddr, sizeof(maddr)) < 0 then begin Result := false; FErrMsg := '链接主机失败!'; Exit; end; recv(sock, rbuf, sizeof(rbuf),0); //链接成功 if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; //服务器标识 sbuf := 'ehlo '+ IntToStr(GetCurrentThreadID) + CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; //请求验证 // sbuf := 'Network';//+ CRLF; sbuf := 'AUTH LOGIN'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //服务器应返回334 if rbuf[0] <> '3' then begin Result := false; FErrMsg := rbuf; Exit; end; useri:=copy(FFromAddr,1,pos('@',FFromAddr)-1); //发送用户名 sbuf := Base64EncodeStr(useri)+ CRLF; // sbuf := EncodeBASE64(useri)+ CRLF; //winsock.send(sock, sbuf[1], Length(sbuf),0); winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //服务器应返回334 if rbuf[0] <> '3' then begin Result := false; FErrMsg := rbuf; Exit; end; //发送密码 sbuf := Base64EncodeStr(FPassword)+ CRLF; // sbuf := EncodeBASE64(FPassword)+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //若正确,服务器应返回235 if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; //来自 sbuf := 'MAIL FROM: <'+ FFromAddr +'>'+ CRLF; //sbuf := 'MAIL FROM: <'+ FShowFromAddr +'>'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; //发送到 sbuf := 'RCPT TO: <'+ FToAddr +'>'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; //抄送到 if FCCAddr <>'' then begin sbuf := 'RCPT TO: <'+ FCCAddr +'>'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; end; //密送到 if FBCCAddr<>'' then begin sbuf := 'RCPT TO: <'+ FBCCAddr +'>'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; end; //准备发送数据 sbuf := 'DATA'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if (rbuf[0] <> '3') or (rbuf[1] <> '5') then begin Result := false; FErrMsg := rbuf; Exit; end; //初始化需要发送的数据 InitSendData; sbuf := FSendData.Text; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end; sbuf := 'QUIT' + CRLF ; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); finally CloseSocket(sock); end;end;end.
 
你把请求验证、发送用户名及发送密码代码段中的 if ... then 代码块注释掉试试,如果可以发送,说明你们的邮件服务器可能不需要验证。 sbuf := 'AUTH LOGIN'+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //服务器应返回334 //把下面的 if 注释掉 {if rbuf[0] <> '3' then begin Result := false; FErrMsg := rbuf; Exit; end;} useri:=copy(FFromAddr,1,pos('@',FFromAddr)-1); //发送用户名 sbuf := Base64EncodeStr(useri)+ CRLF; // sbuf := EncodeBASE64(useri)+ CRLF; //winsock.send(sock, sbuf[1], Length(sbuf),0); winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //服务器应返回334 //把下面的 if 注释掉 {if rbuf[0] <> '3' then begin Result := false; FErrMsg := rbuf; Exit; end;} //发送密码 sbuf := Base64EncodeStr(FPassword)+ CRLF; // sbuf := EncodeBASE64(FPassword)+ CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); //若正确,服务器应返回235 //把下面的 if 注释掉 {if rbuf[0] <> '2' then begin Result := false; FErrMsg := rbuf; Exit; end;}
 
应该不是这儿的问题吧,因为如果我用126的发host写成smtp.126.com而用我们的服务器直接写成ip的话到这儿就出错了{如是ip则用 tmpip:=inet_addr(PChar(FHost)); mhost:=GetHostByAddr(@tmpip,SizeOf(tmpip), AF_INet); } mhost := gethostbyname(pchar(FHost)); if mhost = nil then begin Result := false; FErrMsg := '获取主机地址失败!'; Exit; end;,所以我后来改成注释的部分了,倒时能过去了整个过程序都能过去,只是到最后 sbuf := 'QUIT' + CRLF ; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0);一般正常的应该返回ok而用我们服务器的返回250 AUTH LOGINWebMail [3.7.7.3] ready. http://www.winwebmail.com这是怎么回事呢
 
to szhcracker :能留一下qq号吗,想请教一下,着急的
 
接收邮件服务器现在一般会去判定发送邮件的IP是否是在允许的范围。估计是被拒绝,你可以跟踪看下它返回的说明是什么。2XX是正确3XX是等待完成其它一般都是错误的。
 
是正确的250 AUTH LOGINWebMail [3.7.7.3] ready. http://www.winwebmail.comr?19:15:05:Send Failed502 Error: command not implemented服务器应该没有问题,因为我同事用.net里的类能发的,只是现在有点儿不符合要求,所以想不用他的发
 
我又测试了一下发现了,是执行过sbuf := 'ehlo '+ IntToStr(GetCurrentThreadID) + CRLF; winsock.send(sock, sbuf[1], Length(sbuf),0); recv(sock, rbuf, sizeof(rbuf),0); if rbuf[0] <> '2' then //250 begin Result := false; FErrMsg := rbuf; Exit; end;返回值不同,126的'2', '5', '0', '-', 'm', 'a', 'i', 'l', #13, #10, '2', '5', '0', '-', 'P', 'I', 'P', 'E', 'L', 'I', 'N', 'I', 'N', 'G', #13, #10, '2', '5', '0', '-', 'A', 'U', 'T', 'H', ' ', 'L', 'O', 'G', 'I', 'N', ' ', 'P', 'L', 'A', 'I', 'N', #13, #10, '2', '5', '0', '-', 'A', 'U', 'T', 'H', '=', 'L', 'O', 'G', 'I', 'N', ' ', 'P', 'L', 'A', 'I', 'N', #13, #10, '2', '5', '0', ' ', '8', 'B', 'I', 'T', 'M', 'I', 'M', 'E', #13, #10, #236, #253, #18, #0, #172, '+', '@', #0, '/', #216, #185, #0, #200, #253, #18, #0, #157, 'M', '@', #0, 'd', #216, #18而我们的服务器返回('2', '5', '0', '-', 'S', 'I', 'Z', 'E', #13, #10, '2', '5', '0', ' ', 'A', 'U', 'T', 'H', ' ', 'L', 'O', 'G', 'I', 'N', #13, #10, '.', '7', '.', '7', '.', '3', ']', ' ', 'r', 'e', 'a', 'd', 'y', '.', ' ', ' ', 'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w', '.', 'w', 'i', 'n', 'w', 'e', 'b', 'm', 'a', 'i', 'l', '.', 'c', 'o', 'm', #13, #10, #216, #185, #0, 'X', #216, #185, #0, '#', #0, #0, #0, 'X', #216, #185, #0, '/', #216, #185, #0, #236, #253, #18, #0, #172, '+', '@', #0, '/', #216, #185, #0, #200, #253, #18, #0, #157, 'M', '@', #0, 'd', #216, #18各位知道,我用我们的服务器下边该怎么调用啊
 
我有做好的。。。。。
 
改为if Sock = INVALID_SOCKET then begin Result := False; FErrMsg := '创建Socket失败!'; Exit; end; mhost := gethostbyname(PChar(FHost)); if mhost = nil then begin Result := False; FErrMsg := '获取主机地址失败!'; Exit; end; maddr.sin_family := AF_INET; maddr.sin_port := htons(25); maddr.sin_addr.S_addr := Longint(PLongint(mhost^.h_addr_list^)^); if connect(sock, maddr, SizeOf(maddr)) < 0 then begin Result := False; FErrMsg := '连接主机失败!'; Exit; end;...试试。
 
FHost就用IP地址
 
改了一下能发出去了,现在还有个小问题就是发件人显得是乱码
 
有知道的赶紧说话,解决了结贴了
 
怎么没人说话呢,在foxmail里显示正常,但直接到邮箱看发件人是乱码
 
你的发件人用英文或字母试试(不要用中文),如要用中文,可用Indy控件来做,还有些乱码与邮件服务器或客户端的邮箱编码设置有关。
 
问题解决了,谢谢各位热情帮助
 
后退
顶部