找回密码
 开放注册

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

搜索
查看: 1576|回复: 0

编写SMTP匿名邮件客户端(罗文涛)

[复制链接]

735

主题

1102

回帖

3076

牛毛

二级牛人

积分
3096
QQ
发表于 2009-7-3 10:04:34 | 显示全部楼层 |阅读模式 来自 山东省威海市
1 技术要点:
  实现简单的邮件发送功能的,基于SMTP协议的匿名邮件客户端程序,了解SMTP协议和邮件服务器接收和发送邮件的的原理.

2 关键代码
  //发送邮件函数     
void SendMail()
{
        WSADATA wsa;
        struct hostent *pHostent = NULL;
    SOCKET server = INVALID_SOCKET;
    struct sockaddr_in ServerAddr;
    int ret = 0;
char Buffer[1024]={0};
char TmpUse[100],TmpPWD[100],TmpFromAdd[100],TmpToAdd[100];
    printf("\n        ......................  邮件发送信息  ....................\n\n");
        //初始化Socket
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        {
                printf("初始化Socket失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
        }
        //创建Socket
        server = socket(AF_INET, SOCK_STREAM, 0);
    if (server == INVALID_SOCKET)
    {
                printf("创建Socket失败...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
    }
        //获取SMTP邮件服务器地址
        pHostent = gethostbyname(HostName);
    if (pHostent == NULL)
    {
                printf("获取邮件服务器名称失败...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
        //将获取的SMTP邮件服务器地址转化为ip地址
        ServerAddr.sin_family = AF_INET;
    memcpy(&ServerAddr.sin_addr.S_un.S_addr,pHostent->h_addr_list[0], pHostent->h_length);
    ServerAddr.sin_port = htons(25);
        //通过IP地址连接服务器
        ret = connect(server, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
    if (ret == SOCKET_ERROR)
    {
                printf("连接邮件服务器失败...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
        printf("正在连接 %s...\n", inet_ntoa(ServerAddr.sin_addr));

        ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回连接信息失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("邮件服务器返回连接信息:%s\n", Buffer);
    }
    //发送HELO Server信息
        ret = send(server, "HELO Server\r\n", strlen("HELO Server\r\n"), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送Hello Server欢迎信息失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送HELLO Server欢迎信息!......\n");     
    }
        ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回HELLO Server信息失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("邮件服务器返回helloServer信息:%s\n", Buffer);
    }
        //发送AUTH LOGIN信息
        ret = send(server, "AUTH LOGIN\r\n", strlen("AUTH LOGIN\r\n"), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送AUTH LOGIN信息失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送AUTH LOGIN信息!......\n");     
    }   
        ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回AUTH LOGIN信息失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("邮件服务器返回AUTH LOGIN信息:%s\n", Buffer);
    }
        //将用户名经行Base64加密以后发送
        string strEncodeUser = bs.base64_encode(User);
    sprintf(TmpUse,"%s\r\n",strEncodeUser.c_str());
        ret = send(server,TmpUse, strlen(TmpUse), 0);
        if (ret == SOCKET_ERROR)
    {
                printf("发送用户名失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
        }
        else
        {
                printf("正在发送用户名!...\n");
        }
        ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回用户名信息失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("服务器返回用户名信息:%s\n", Buffer);
    }
        //将密码进行Base64加密以后发送
        string strEncodePWD = bs.base64_encode(PWD);
        sprintf(TmpPWD,"%s\r\n",strEncodePWD.c_str());
        ret = send(server,TmpPWD, strlen(TmpPWD), 0);
        if (ret == SOCKET_ERROR)
    {
                printf("发送密码失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
        }
        else
        {
                printf("正在发送密码!...\n");
        }
        ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回密码信息失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("服务器返回密码信息:%s\n", Buffer);
    }
        //设置服务器的Mail From地址(此处必须您的真实的邮件发送地址)
        sprintf(TmpFromAdd,"MAIL FROM: <%s>\r\n",FromAdds);
        ret = send(server, TmpFromAdd, strlen(TmpFromAdd), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送Mail From:失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送Mail From: %s\n",FromAdds);     
    }   
    ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("服务器返回邮件发送地址错误!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();   
                gets(os);
                exit(1);
    }
    else
    {
                printf("服务器返回Mail From信息:%s\n", Buffer);
    }
        //设置邮件服务器的接受人地址
        sprintf(TmpToAdd,"RCPT TO: <%s>\r\n",SendAdds);
        ret = send(server, TmpToAdd, strlen(TmpToAdd), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送RCPT TO地址错误!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送RCPT TO地址为%s\n",SendAdds);     
    }   
         
    ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("邮件服务器返回Rcpt to错误...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {   
                printf("服务器返回Rcpt to信息:%s\n", Buffer);
    }

        //向邮件服务器发送"发送日期时间"信息
        ret = send(server, "Data\r\n", strlen("Data\r\n"), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送(Data)时间错误!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送(Data)时间...\n");     
    }   
         
    ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("服务器返回(Data)时间失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();   
                gets(os);
                exit(1);
    }
    else
    {
                printf("服务器返回(Data)时间:%s\n", Buffer);
    }
        //开始发送邮件数据(邮件体+邮件头)
        //该处的MailData是邮件数据,其中的邮件头中
        //"From: \"发送者昵称\"<xxx@126.com>\r\n"可以自定义
        ret = send(server, MailData, strlen(MailData), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送邮件(MailData)正文失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("正在发送邮件(MailData)正文:\n%s\n",MailData);
    }

    ZeroMemory(Buffer, sizeof(Buffer));
    ret = recv(server, Buffer, sizeof(Buffer), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("服务器返回邮件(MailData)正文失败!...\n");     
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();   
                gets(os);
                exit(1);
    }
    else
    {
                printf("服务器返回邮件(MailData)正文:\n%s\n", Buffer);
    }
        //发送完毕,向服务器发送退出命令
        ret = send(server, "QUIT\r\n", strlen("QUIT\r\n"), 0);
    if (ret == SOCKET_ERROR)
    {
                printf("发送(QUIT)断开连接命令失败!...\n");
                if (server != INVALID_SOCKET)
                {
                        closesocket(server);
                }
        WSACleanup();
                gets(os);
                exit(1);
    }
    else
    {
                printf("成功断开服务器连接!...\n");     
    }   
    printf("\n发送邮件完成!...\n");
        gets (os);
}
3 主要原理
   伪造邮件数据格式的,文件头信息"From: \"发送者昵称\"<xxx@126.com>\r\n"
邮件头的具体格式:
"From: \"发送者昵称\"<xxx@126.com>\r\n"
"To: \"收件人昵称 \"<xxx @126.com>\r\n"
"Date: Mon, 25 Oct 2005 14:24:27 +0800\r\n"
"Subject:主题内容\r\n\r\n"
邮件体的格式:
"邮件体 \r\n.\r\n"
将邮件头和邮件体连成一个字符串发送到邮件服务器,自此整个邮件匿名邮件的发送过程就基本完成了

126,163等邮箱都对新注册的用户都做了SMTP/POP3的限制,不允许用户直接访问SMTP/POP3协议了.如果新注册用户访问该SMTP服务器,就会出现(550 用户被锁定)的错误提示,大家可以测试一下.言归正传,如果要QQ邮箱支持匿名发送邮件,就必须在,”QQ邮箱->设置->账户->POP3/IMAP/SMTP服务”这里开启QQ邮箱的SMTP服务,
您需要登录后才可以回帖 登录 | 开放注册

本版积分规则

帮助|Archiver|小黑屋|通信管理局专项备案号:[2008]238号|NB5社区 ( 皖ICP备08004151号;皖公网安备34010402700514号 )

GMT+8, 2025-4-27 18:37 , Processed in 0.160774 second(s), 35 queries .

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表