用C写的邮件发送程序

news/2024/7/3 5:52:17

编程环境:WinXP SP2,Visual Studio 2005 Pro

参考资料:《HowTo.SMTP》,《SendMail》(NextFly写的),《MSDN 2005》


// SendMail.cpp : 定义控制台应用程序的入口点。
//

#i nclude "stdafx.h"

#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

const char *MailData = "From: /"88250/"<dl88250@126.com>/r/n"
      "Subject: This is only a test mail! ^^/r/n./r/n";


int main(int argc, char *argv[])
{
  
    WSADATA wsaData;
 WORD wVersionRequested = MAKEWORD(2, 2);
    struct hostent *pHostent = NULL;
    SOCKET server = INVALID_SOCKET;
    struct sockaddr_in service;
    int retConnect = 0;
    char Buffer[1024] = {0};
    
 if(WSAStartup(wVersionRequested, &wsaData) != 0){
  printf("Error at WSAStartup()/n");
  goto WSACleanup;
    }
    
    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);        //Create a Socket

    if(server == INVALID_SOCKET){
  printf("Error at socket(): %ld/n", WSAGetLastError());
        goto WSACleanup;
    }
    
    pHostent = gethostbyname("smtp.126.com");              //Get the Mail Server Name
    if(pHostent == NULL){
  printf("The Host Name is Invalid.../n");
        goto WSACleanup;
    }
    
    service.sin_family = AF_INET;
    memcpy(&service.sin_addr.s_addr, pHostent->h_addr_list[0], pHostent->h_length);
    service.sin_port = htons(25);
 
    //Connect to the remote Mail Server
    retConnect = connect(server, (struct sockaddr*)&service, sizeof(service));
    if(retConnect == SOCKET_ERROR){
  printf("Failed to connect./n");
        goto WSACleanup;
    }
    
    printf("Connect to %s..../n", inet_ntoa(service.sin_addr));
    
    //Receive Data From the Mail Server
 ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Failed to connect./n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }
    
    //Send "HELO Server..../r/n" to the Mail Server
    retConnect = send(server, "HELO Server..../r/n", strlen("HELO Server..../r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send HELO to the Mail Failure./n");
        goto WSACleanup;
    }else{
    printf("HELO Server..../n");   
    }  
    
    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Failed to connect./n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send "AUTH LOGIN/r/n" to the Mail Server
    retConnect = send(server, "AUTH LOGIN/r/n", strlen("AUTH LOGIN/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send /"AUTH LOGIN/" to Mail Failure./n");
        goto WSACleanup;
    }else{
  printf("AUTH LOGIN/n");   
    }      

    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From Mail Server Failure./n");    
        goto WSACleanup;     
    }else{ 
  printf("%s/n", Buffer);
    }
  
    //Send UserName to the Mail Server. The UserName is Encoded by Base64.
    retConnect = send(server, "bGJleW9uZDRrb21h==/r/n", strlen("bGJleW9uZDRrb21h==/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send UserName to the Mail Failure./n");
        goto WSACleanup;
    }else{
  printf("UserName/n");   
    }      
        
    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From the Mail Server Failure./n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send Password to the Mail Server The Password is Encoded by Base64.
    retConnect = send(server, "bGJleW9uZDRrb21h=/r/n", strlen("bGJleW9uZDRrb21h=/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send Password to Mail Failure./n");
        goto WSACleanup;
    }else{
  printf("Password/n");   
    }  
    
    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From the Mail Server Failure./n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send "Mail From: " File to the Mail Server, sender's Mail Address
    retConnect = send(server, "MAIL FROM: <
lbeyond4koma@126.com>/r/n", strlen("MAIL FROM: <lbeyond4koma@126.com>/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send /"Mail From: /" to Mail Failure./n");
        goto WSACleanup;
    }else{
  printf("MAIL FROM: <
lbeyond4koma@126.com>/n");   
    }  
    
    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From Mail Server Failure./n");    
        goto WSACleanup;     
    }else{
  Buffer[retConnect] = ' ';
        printf("%s/n", Buffer);
    }

    //Send "RCPT TO: " File to the Mail Server, receiver 's Mail Address
    retConnect = send(server, "RCPT TO: <
dl88250@gmail.com>/r/n", strlen("RCPT TO: <dl88250@gmail.com>/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send /"RCPT TO: /" to Mail Failure./n");
        goto WSACleanup;
    }else{
  printf("RCPT TO: <
dl88250@gmail.com>/n");   
    }  
    
    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From the Mail Server Failure./n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send "Data" Fiele to the Mail Server, start to Send mail
    retConnect = send(server, "Data/r/n", strlen("Data/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send /"Data/" Field to Mail Failure.../n");
        goto WSACleanup;
    }else{
  printf("Data/n");   
    }  

    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From Mail Server Failure.../n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send Mail data to the the Mail Server
    retConnect = send(server, MailData, strlen(MailData), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send Context Of Mail to Mail Failure.../n");
        goto WSACleanup;
    }else{
  printf("%s/n", MailData);
    }

    //Receive Data From the Mail Server
    ZeroMemory(Buffer, sizeof(Buffer));
    retConnect = recv(server, Buffer, sizeof(Buffer), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Receive Data From Mail Server Failure.../n");    
        goto WSACleanup;     
    }else{
        printf("%s/n", Buffer);
    }

    //Send "QUIT" Context to the Mail Server
    retConnect = send(server, "QUIT/r/n", strlen("QUIT/r/n"), 0);
    if(retConnect == SOCKET_ERROR){
  printf("Send /"Quit/" to Mail Failure.../n");
        goto WSACleanup;
    }else{
  printf("Quit/n");   
    }  
   
    printf("Send Mail Successful!/n");
              
 WSACleanup:{
  if(server != INVALID_SOCKET){
   closesocket(server);
        }
        WSACleanup();        
 }
    system("pause");
 return 0;
}

其中需要注意的是寄件人地址与邮件内容里的邮件地址的关系:

寄件人的地址必须和你用的连接帐号一致。帐号和密码是使用Base64编码的(关于什么是Base64编码请到http://www.ynutx.net/blog/user1/Myth/archives/2006/1682.html下面看看,它的C实现代码在下面)。。。。

而在邮件内容里的地址只是一个告诉邮件服务器这封信是谁发的。可以和你所使用的发送帐号不一致!也就是说你可以伪造别人的地址进行邮件发送。。。。

哎,不要干什么干事哟^_^!

好了,下面就是Base64编码与解码的实现代码了:

#i nclude <stdio.h>
#i nclude <string.h>

char *ch64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

unsigned char *encode(unsigned char *src, int srclen)
{
 int n, buflen, i, j;
 int pading = 0;
 unsigned char *buf;
 static unsigned char *dst;

 buf = src;
 buflen = n = srclen;
 if(n % 3 != 0){  /* pad with '=' by using a temp buffer */
  pading = 1;
  buflen = n + 3 - n % 3;
  buf = malloc(buflen + 1);
  memset(buf, 0, buflen + 1);
  memcpy(buf, src, n);
  for(i=0;i<3-n%3;i++){
   buf[n+i] = '=';
  }
 }
 dst = malloc(buflen * 4 / 3 + 1);
 memset(dst, 0, buflen * 4 / 3 + 1);
 for(i = 0, j = 0; i < buflen; i += 3, j += 4){
  dst[j] = (buf[i] & 0xFC) >> 2;
  dst[j+1] = ((buf[i] & 0x03) << 4) + ((buf[i+1] & 0xF0) >> 4);
  dst[j+2] = ((buf[i+1] & 0x0F) << 2) + ((buf[i+2] & 0xC0) >> 6);
  dst[j+3] = buf[i+2] & 0x3F;
 }
 for(i = 0; i < buflen * 4 / 3; i++){ /* map 6 bit value to base64 ASCII character */
  dst[i] = ch64[dst[i]];
 }
 if(pading){
  free(buf);
 }
 return dst;
}

unsigned char *decode(unsigned char *src)
{
 int n, i, j;
 unsigned char *p;
 static unsigned char *dst;

 n = strlen(src);
 for(i=0;i<n;i++){ /* map base64 ASCII character to 6 bit value */
  p = strchr(ch64, src[i]);
 if(!p){
  break;
 }
 src[i] = p - ch64;
 }
 dst = malloc(n * 3 / 4 + 1);
 memset(dst, 0, n * 3 / 4 + 1);
 for(i = 0, j = 0; i < n; i += 4, j += 3){
  dst[j] = (src[i] << 2) + ((src[i+1] & 0x30) >> 4);
  dst[j+1] = ((src[i+1] & 0x0F) << 4) + ((src[i+2] & 0x3C) >> 2);
  dst[j+2] = ((src[i+2] & 0x03) << 6) + src[i+3];
 }
 return dst;
}

int main()
{
 char *src = "lbeyond4koma";
 unsigned char *dst1;
 unsigned char *dst2;
 unsigned int i;

 dst1 = encode(src, strlen(src)); /* the second parameter must accord with the first one */
 printf("%s/n", dst1);
 dst2 = decode(dst1);
 for(i = 0; i < _msize(dst2); i++){
  printf("%c",dst2[i]);
 }
 free(dst1);
 free(dst2);
 return 0;
}
 


http://www.niftyadmin.cn/n/1999559.html

相关文章

2、nginx配置文件

2、nginx配置文件 user [user] [group];//运行nginx的用户(组)&#xff08;只能在全局设置&#xff09; worker process number|auto;//允许生成的worker process数&#xff08;只能在全局设置&#xff0c;通常设置成和cpu的数量相等 &#xff09; pid file;//nginx进程的Pid存…

为什么要用Linux

为什么要用Linux "我已经半年没有使用 Windows 的方式工作了。Linux 高效的完成了我所有的工作。 GNU/Linux 不是每个人都想用的。如果你只需要处理一般的事务&#xff0c;打游戏&#xff0c;那么你不需要了解下面这些了。 我不是一个狂热的自由软件份子&#xff0c…

Android Studio生成APK自动追加版本号、自定义apk名称、指定签名证书文件

你也可以查看我的其他同类文章&#xff0c;也会让你有一定的收货&#xff01; 生成APK自动追加版本号 可自动区分debug和release&#xff0c;并追加版本号&#xff1a; 打开 build.gradle 在 android 节点中插入下面代码 第一种&#xff1a; applicationVariants.all{ variant…

python 信号量_Python的互斥锁与信号量详解

并发与锁多个线程共享数据的时候&#xff0c;如果数据不进行保护&#xff0c;那么可能出现数据不一致现象&#xff0c;使用锁&#xff0c;信号量、条件锁互斥锁1. 互斥锁&#xff0c;是使用一把锁把代码保护起来&#xff0c;以牺牲性能换取代码的安全性&#xff0c;那么Rlock后…

opencl获取gpu信息_国产GPU目前对于OpenGL、OpenCL的支持都如何?

为了回答这个问题&#xff0c;我特意去查了一下国内GPU第一的厂商景嘉微&#xff0c;从目前的产品线来看&#xff0c;已经上市的两款主打产品是JM7200和JM7201&#xff0c;由于官网有关这两款芯片的介绍实在太少&#xff0c;有一些数据可能不准确。我们先来看这两款产品的一些参…

基于Visual Studio 2003/2005的Office插件开发FAQ

基于Visual Studio 2003/2005的Office插件开发FAQ 最近处理了好几个Office Addin的问题&#xff0c;总结出一些经验&#xff0c;在此与大家分享一下。首先介绍一些注意点1. 一定要把宏安全级别设置为Medium以下&#xff0c;默认是High&#xff0c;肯定不允许运行任何Addin&…

es6中新增数组的方法

1. Array.from 这个东西就是把一些集合&#xff0c;或者长的像数组的伪数组转换成真的数组&#xff0c;比如arguments&#xff0c;js选择器找到dom集合, 还有对象模拟的数组 var obj { 0 : 1, length : 1 } Array.from(obj / arguments / 伪数组) //返回的是一个数组 [].slice…

nvidia控制面板点了没反应win7_Win7系统打不开Nvidia控制面板提示“停止工作”怎么办...

众所周知&#xff0c;显卡是win7系统电脑中比较重要的部件&#xff0c;如果显卡出现问题&#xff0c;会导致显示屏打不开或者显示画面看不请&#xff0c;还好Win7系统中有个Nvidia控制面板&#xff0c;能够对显卡进行设置&#xff0c;提升显卡功能。但有用户说打不开Nvidia控制…