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; tmpipWORD;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.