前言
C语言实现SMTP发邮件(SSL协议)
这里作者采用OpenSSL来发送和解析SSL协议,并实验SMTP发邮件
以网易云smtp.163.com为例
引用库
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <unistd.h> #include <sys/time.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <assert.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h>
示例代码
#define SMTP_PORT 465 #define SMTP_HOST ("smtp.163.com") #define SMTP_USER ("XXXXX") // base64编码 #define SMTP_PAWD ("XXXXX") // base64编码 int sendMessage(char *message, char *form, char *to) { struct hostent *host = NULL; struct sockaddr_in serverAddr; SSL_CTX *ctx = NULL; SSL *ssl = NULL; char buf[320] = {0}; char *messagebuf = NULL; char ip[32] = {0}; int sockfd = 0; host = gethostbyname(SMTP_HOST); if (host == NULL) { return -1; } ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) { return -1; } inet_ntop(host->h_addrtype, host->h_addr_list[0], ip, sizeof(ip)); memset(&serverAddr, 0, sizeof(struct sockaddr_in)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SMTP_PORT); serverAddr.sin_addr.s_addr = inet_addr(ip); sockfd = socket(PF_INET, SOCK_STREAM, 0); if (sockfd < 0) { return -1; } if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) < 0) { return -1; } ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); if (SSL_connect(ssl) != 1) { return -1; } // HELO sprintf(buf, "%s", "EHLO smtp.163.com \r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // AUTH LOGIN 身份认证 sprintf(buf, "%s", "AUTH LOGIN\r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送账号 sprintf(buf, "%s\r\n", SMTP_USER); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送密码 sprintf(buf, "%s\r\n", SMTP_PAWD); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送发件人 sprintf(buf, "%s", "MAIL FROM: <"); strcat(buf, form); strcat(buf, ">\r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送收件人 sprintf(buf, "%s", "RCPT TO:<"); strcat(buf, to); strcat(buf, ">\r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送邮件内容标识 sprintf(buf, "%s", "DATA\r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } // 发送邮件 while (1) { tmp = (char *)calloc(sizeof(char), 13 + strlen(box)); if(tmp){ break; } sleep(1); } sprintf(messagebuf, "%s\r\n.\r\n", message); SSL_write(ssl, messagebuf, strlen(messagebuf)); if (SSL_read(ssl, messagebuf, strlen(messagebuf)) <= 0) { return -1; } free(messagebuf); // 断开连接 sprintf(buf, "%s", "QUIT\r\n"); SSL_write(ssl, buf, strlen(buf)); if (SSL_read(ssl, buf, 320) <= 0) { return -1; } close(sockfd); SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); return 0; } int main() { char message[] = "From: test<XXX@163.com>\r\n" "TO: test<XXX@qq.com>\r\n" "Subject: test\r\n\r\n" "hello world\r\n"; sendMessage(message, "XXX@163.com", "XXX@qq.com"); }
编译命令
GCC:
gcc ./sendMessage.c -o sendMessage.out -lssl
最新评论