过程如下:
220 hz-b-126smtp1.126.com SMTP Server for Netease [466] e8241e55-7706-40c6-86bc-145 helo smtp.126.com 250 hz-b-126smtp1.126.com e8241e55-7706-40c6-86bc-14581e3c9753 auth login //登录 334 VXNlcm5hbWU6 e8241e55-7706-40c6-86bc-14581e3c9753 ZmVpZXI3NTAx //这个是用base64编码的用户名 334 UGFzc3dvcmQ6 e8241e55-7706-40c6-86bc-14581e3c9753 xxxxxx //这个是用base64编码的密码,我用xxxxxx来表示密码 235 OK, go ahead (#2.0.0) e8241e55-7706-40c6-86bc-14581e3c9753 mail from:<[email protected]> 250 2.0.0 OK e8241e55-7706-40c6-86bc-14581e3c9753 rcpt to:<[email protected]> 250 2.0.0 OK e8241e55-7706-40c6-86bc-14581e3c9753 data //开始输入邮件内容 354 Start mail input; end with <CRLF>.<CRLF> e8241e55-7706-40c6-86bc-14581e3c9753 from:<[email protected]> to:<[email protected]> subject:smtp test //主题和正文之间要空一行 this is smtp test . //用.和换行来表示结束 250 2.0.0 OK e8241e55-7706-40c6-86bc-14581e3c9753 quit //退出 221 2.0.0 Bye e8241e55-7706-40c6-86bc-14581e3c9753 失去了跟主机的连接。
base64.h:
/* Copyright (c) 2006-2007, Philip Busch <[email protected]> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Base64 header. * @ingroup base64 */ #ifndef _BASE64_H #define _BASE64_H void base64_encode_block(unsigned char out[4], const unsigned char in[3], int len); int base64_decode_block(unsigned char out[3], const unsigned char in[4]); size_t base64_encoded_size(size_t len); size_t base64_decoded_size(size_t len); void base64_encode_binary(char *out, const unsigned char *in, size_t len); int base64_decode_binary(unsigned char *out, const char *in); char *base64_encode(const char *in, size_t size); char *base64_decode(const char *in); #endif /* ! _BASE64_H */
/* Copyright (c) 2006-2007, Philip Busch <[email protected]> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Base64 implementation. * @ingroup base64 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "base64.h" #define XX 100 /** @var base64_list * A 64 character alphabet. * * A 64-character subset of International Alphabet IA5, enabling * 6 bits to be represented per printable character. (The proposed * subset of characters is represented identically in IA5 and ASCII.) * The character "=" signifies a special processing function used for * padding within the printable encoding procedure. * * \verbatim Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y \endverbatim */ static const char base64_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const int base64_index[256] = { XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, 62, XX, XX, XX, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, XX, XX, XX, XX, XX, XX, XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, XX, XX, XX, XX, XX, XX, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, }; /** Encode a minimal memory block. This function encodes a minimal memory area * of three bytes into a printable base64-format sequence of four bytes. * It is mainly used in more convenient functions, see below. * * @attention This function can't check if there's enough space at the memory * memory location pointed to by \c out, so be careful. * * @param out pointer to destination * @param in pointer to source * @param len input size in bytes (between 0 and 3) * @returns nothing * * @ingroup base64 */ void base64_encode_block(unsigned char out[4], const unsigned char in[3], int len) { out[0] = base64_list[in[0] >> 2]; out[1] = base64_list[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; out[2] = (unsigned char) ( len > 1 ? base64_list[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)] : '='); out[3] = (unsigned char) (len > 2 ? base64_list[in[2] & 0x3f] : '='); } /** Decode a minimal memory block. This function decodes a minimal memory area * of four bytes into its decoded equivalent. It is mainly used in more * convenient functions, see below. * * @attention This function can't check if there's enough space at the memory * memory location pointed to by \c out, so be careful. * * @param out pointer to destination * @param in pointer to source * @returns -1 on error (illegal character) or the number of bytes decoded * * @ingroup base64 */ int base64_decode_block(unsigned char out[3], const unsigned char in[4]) { int i, numbytes = 3; char tmp[4]; for (i = 3; i >= 0; i--) { if (in[i] == '=') { tmp[i] = 0; numbytes = i - 1; } else { tmp[i] = base64_index[(unsigned char) in[i]]; } if (tmp[i] == XX) return (-1); } out[0] = (unsigned char) (tmp[0] << 2 | tmp[1] >> 4); out[1] = (unsigned char) (tmp[1] << 4 | tmp[2] >> 2); out[2] = (unsigned char) (((tmp[2] << 6) & 0xc0) | tmp[3]); return (numbytes); } /** Compute size of needed storage for encoding. This function computes the * \e exact size of a memory area needed to hold the result of an encoding * operation, not including the terminating null character. * * @param len input size * @returns output size * * @ingroup base64 */ size_t base64_encoded_size(size_t len) { return (((len + 2) / 3) * 4); } /** Compute size of needed storage for decoding. This function computes the * \e estimated size of a memory area needed to hold the result of a decoding * operation, not including the terminating null character. Note that this * function may return up to two bytes more due to the nature of Base64. * * @param len input size * @returns output size * * @ingroup base64 */ size_t base64_decoded_size(size_t len) { return ((len / 4) * 3); } /** Encode an arbitrary size memory area. This function encodes the first * \c len bytes of the contents of the memory area pointed to by \c in and * stores the result in the memory area pointed to by \c out. The result will * be null-terminated. * * @attention This function can't check if there's enough space at the memory * memory location pointed to by \c out, so be careful. * * @param out pointer to destination * @param in pointer to source * @param len input size in bytes * @returns nothing * * @ingroup base64 */ void base64_encode_binary(char *out, const unsigned char *in, size_t len) { int size; size_t i = 0; while (i < len) { size = (len - i < 4) ? len - i : 4; base64_encode_block((unsigned char *) out, in, size); out += 4; in += 3; i += 3; } *out = '\0'; } /** Decode an arbitrary size memory area. This function decodes the * base64-string pointed to by \c in and stores the result in the memory area * pointed to by \c out. The result will \e not be null-terminated. * * @attention This function can't check if there's enough space at the memory * memory location pointed to by \c out, so be careful. * * @param out pointer to destination * @param in pointer to source * @returns -1 on error (illegal character) or the number of bytes decoded * * @ingroup base64 */ int base64_decode_binary(unsigned char *out, const char *in) { size_t len = strlen(in), i = 0; int numbytes = 0; while (i < len) { if ((numbytes += base64_decode_block(out, (unsigned char *) in)) < 0) return (-1); out += 3; in += 4; i += 4; } return (numbytes); } /** Encode a string. This is a convenience function. It encodes the first * \c size bytes of the string pointed to by \c in, stores the null-terminated * result in a newly created memory area and returns a pointer to it. * * @attention After a call to base64_encode(), you have to free() the result * yourself. * * @param in pointer to string * @param size strlen * @returns NULL on error (not enough memory) or a pointer to the encoded result * * @ingroup base64 */ char *base64_encode(const char *in, size_t size) { char *out; size_t outlen; if (in == NULL) return (NULL); if (size == 0) size = strlen(in); outlen = base64_encoded_size(size); if ((out = (char *) malloc(sizeof(char) * (outlen + 1))) == NULL) return (NULL); base64_encode_binary(out, (unsigned char *) in, size); return (out); } /** Decode a string. This is a convenience function. It decodes the * null-terminated string pointed to by \c in, stores the result in a newly * created memory area and returns a pointer to it. The result will be * null-terminated. * * @attention After a call to base64_decode(), you have to free() the result * yourself. * * @param in pointer to string * @returns NULL on error (not enough memory) or a pointer to the decoded result * * @ingroup base64 */ char *base64_decode(const char *in) { char *out; size_t outlen; int numbytes; outlen = base64_decoded_size(strlen(in)); if ((out = (char *) malloc(sizeof(char) * (outlen + 1))) == NULL) return (NULL); if ((numbytes = base64_decode_binary((unsigned char *) out, in)) < 0) { free(out); return (NULL); } *(out + numbytes) = '\0'; return (out); }
#include <io.h> #include <WinSock2.h> #include <stdio.h> #include "base64.h" #pragma comment(lib,"ws2_32.lib") void sendmail_write(const int sock, const char *str, const char *arg) { char buf[1024]; if (arg != NULL) sprintf(buf, str, arg); else sprintf(buf, str); send(sock, buf, strlen(buf), 0); printf("%s", buf); } void read_response(const int sock) { char buf[1024]={0}; recv(sock, buf, sizeof buf, 0); printf("%s", buf); } int sendmail(const char *from, const char *to, const char *subject, const char *body, const char *hostname, const int port, const char *b64User, const char *b64Pass) { struct hostent *host; struct sockaddr_in saddr_in; int sock = 0; WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { return -1; } sock = socket(AF_INET, SOCK_STREAM, 0); host = gethostbyname(hostname); saddr_in.sin_family = AF_INET; saddr_in.sin_port = htons((u_short) port); saddr_in.sin_addr.s_addr = 0; memcpy((char*) &(saddr_in.sin_addr), host->h_addr, host->h_length); if (connect(sock, (struct sockaddr*) &saddr_in, sizeof(saddr_in)) == -1) { return -2; } sendmail_write(sock, "HELO %s\n", hostname); read_response(sock); sendmail_write(sock, "AUTH LOGIN\n", NULL); read_response(sock); sendmail_write(sock, "%s\n", b64User); read_response(sock); sendmail_write(sock, "%s\n", b64Pass); read_response(sock); sendmail_write(sock, "MAIL FROM:<%s>\n", from); read_response(sock); sendmail_write(sock, "RCPT TO:<%s>\n", to); read_response(sock); sendmail_write(sock, "DATA\n", NULL); // begin data read_response(sock); sendmail_write(sock, "From:<%s>\n", from); sendmail_write(sock, "To:<%s>\n", to); sendmail_write(sock, "Subject:%s\n", subject); sendmail_write(sock, "\n", NULL); sendmail_write(sock, "%s\n", body); // data sendmail_write(sock, ".\n", NULL); // end data read_response(sock); sendmail_write(sock, "QUIT\n", NULL); // terminate closesocket(sock); return 0; } int main(int argc, char *argv[]) { char user[25], pass[25]; char *pB64user, *pB64pass; printf("Input username:\n"); scanf("%s", user); printf("Input password:\n"); scanf("%s", pass); pB64user = base64_encode(user, strlen(user)); pB64pass = base64_encode(pass, strlen(pass)); int ret = sendmail("[email protected]", "[email protected]", "sent by c", "using c", "smtp.126.com", 25, pB64user, pB64pass); if (ret != 0) fprintf(stderr, "Failed to send mail (code: %i).\n", ret); else fprintf(stdout, "Mail successfully sent.\n"); return ret; }