BASE64编码及SMTP协议简单实现

通过这个简单的Demo程序,可以了解BASE64的编码方法和SMTP协议的报文格式,最终实现一个发送邮件的程序。


base64编解码头文件<base64.h>

#ifndef _Base64_H__
#define _Base64_H__

#include <stdio.h>

char *base64_encode(const char *input, const size_t length,char *output);
char *base64_decode(const char *input,char *output);

#endif

base64编解码源文件<base64.c>

#include "base64.h"

const char base64_index[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 16 * 16  
const int base64_decode_map[256] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0   - 15  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16  - 31  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32  - 47  
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48  - 63  
	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64  - 79  
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80  - 95  
	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96  - 111  
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112 - 127  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128 - 143  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144 - 159   
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160 - 175  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176 - 191  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192 - 207  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208 - 223  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224 - 239  
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240 - 255  
};


char *base64_encode(const char *input, const size_t length, char *output)
{
	*output = '\0';
	if (input == NULL || length < 1) return output;

	char *p = (char*)input;
	char *p_dst = (char*)output;;
	char *p_end = (char*)input + length;
	int  loop_count = 0;

	// 0x30 -> 00110000  
	// 0x3C -> 00111100  
	// 0x3F -> 00111111  
	while (p_end - p >= 3) {
		*p_dst++ = base64_index[(p[0] >> 2)];
		*p_dst++ = base64_index[((p[0] << 4) & 0x30) | (p[1] >> 4)];
		*p_dst++ = base64_index[((p[1] << 2) & 0x3C) | (p[2] >> 6)];
		*p_dst++ = base64_index[p[2] & 0x3F];
		p += 3;
	}

	if (p_end - p > 0) {
		*p_dst++ = base64_index[(p[0] >> 2)];
		if (p_end - p == 2) {
			*p_dst++ = base64_index[((p[0] << 4) & 0x30) | (p[1] >> 4)];
			*p_dst++ = base64_index[(p[1] << 2) & 0x3C];
			*p_dst++ = '=';
		}
		else if (p_end - p == 1) {
			*p_dst++ = base64_index[(p[0] << 4) & 0x30];
			*p_dst++ = '=';
			*p_dst++ = '=';
		}
	}

	*p_dst = '\0';
	return output;
}
char *base64_decode(const char *input, char *output)
{
	output[0] = '\0';
	if (input == NULL || output == NULL)
		return output;

	int input_len = strlen(input);
	if (input_len < 4 || input_len % 4 != 0)
		return output;

	// 0xFC -> 11111100  
	// 0x03 -> 00000011  
	// 0xF0 -> 11110000  
	// 0x0F -> 00001111  
	// 0xC0 -> 11000000  
	char *p = (char*)input;
	char *p_out = output;
	char *p_end = (char*)input + input_len;
	for (; p < p_end; p += 4) {
		*p_out++ = ((base64_decode_map[p[0]] << 2) & 0xFC) | ((base64_decode_map[p[1]] >> 4) & 0x03);
		*p_out++ = ((base64_decode_map[p[1]] << 4) & 0xF0) | ((base64_decode_map[p[2]] >> 2) & 0x0F);
		*p_out++ = ((base64_decode_map[p[2]] << 6) & 0xC0) | (base64_decode_map[p[3]]);
	}

	if (*(input + input_len - 2) == '=') {
		*(p_out - 2) = '\0';
	}
	else if (*(input + input_len - 1) == '=') {
		*(p_out - 1) = '\0';
	}
	return output;
}

发送邮件主程序<demo.c>

#include <stdio.h>
#include <stdlib.h>
#include "base64.h"
#include <winsock.h>

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

int init_socket();
void socket_close();
SOCKET socket_connect(const char * hostname, int port);
void get_sockbuf();
void send_socket(const char *data);

SOCKET sockfd = 0;

int main()
{
	char data[1024] = { 0 };
	char base64_data[2048] = { 0 };
	int i = 0;
	init_socket();
	sockfd = socket_connect("smtp.qq.com", 25);

	//接收服务器信息
	get_sockbuf();

	//发送helo信息
	send_socket("helo smtp.qq.com\r\n");
	//接收服务器应答
	get_sockbuf();

	//发送登录请求
	send_socket("auth login\r\n");
	//接收服务器应答
	get_sockbuf();

	//发送编码后的邮箱账号
	memset(data, 0, sizeof(data));
	strcpy(data, "你自己的QQ号@qq.com");
	base64_encode(data, strlen(data), base64_data);
	i = strlen(base64_data);
	base64_data[i] = '\r';
	base64_data[i+1] = '\n';
	send_socket(base64_data);
	//接收服务器应答
	get_sockbuf();

	//发送编码后的邮箱密码
	memset(data, 0, sizeof(data));
	memset(base64_data, 0, sizeof(base64_data));
	strcpy(data, "你QQ邮箱的密码");
	base64_encode(data, strlen(data), base64_data);
	i = strlen(base64_data);
	base64_data[i] = '\r';
	base64_data[i + 1] = '\n';
	send_socket(base64_data);
	//接收服务器应答
	get_sockbuf();

	//mail from
	send_socket("mail from:<你自己的QQ号@qq.com>\r\n");
	//接收服务器应答
	get_sockbuf();

	//rcpt to
	send_socket("rcpt to:<接收邮件的QQ号@qq.com>\r\n");
	//接收服务器应答
	get_sockbuf();

	//正文
	send_socket("data\r\n");
	send_socket("subject:test\r\n");
	send_socket("\r\nhello!\r\n.\r\n");
	//接收服务器应答
	get_sockbuf();

	//退出
	send_socket("quit\r\n");
	//接收服务器应答
	get_sockbuf();
	socket_close();
	system("pause");
}

void send_socket(const char *data)
{
	if (send(sockfd, data, strlen(data), 0) < 0)
	{
		printf("发送失败!\n");
		return;
	}
	printf("%s", data);
}
void get_sockbuf()
{
	static char buf[1024] = { 0 };
	memset(buf, 0, sizeof(buf));
	if (recv(sockfd, buf, sizeof(buf), 0) < 0)
	{
		return;
	}
	printf("%s", buf);
}

int init_socket()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		return -1;
	}

	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return -1;
	}
	return 0;
}

SOCKET socket_connect(const char * hostname, int port)//连接套接字
{
	struct hostent*host;
	unsigned long ip = 0;

	if (init_socket() == -1)
		return 0;
	SOCKET st = socket(AF_INET, SOCK_STREAM, 0);
	if (st == 0)
		return 0;
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);

	
	ip = inet_addr(hostname);
	if (ip == INADDR_NONE)
	{
		host = gethostbyname(hostname);
		addr.sin_addr = *((struct in_addr*)(host->h_addr_list[0]));
	}
	else
	{
		addr.sin_addr.s_addr = inet_addr(hostname);
	}

	if (connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		printf("连接失败\n");
		return 0;
	}
	else
	{
		return st;
	}
}

void socket_close()
{
	closesocket(sockfd);
	WSACleanup();
}

仅仅这三个文件我们就可以实现一个小小的发送邮件的程序了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值