📄 ncbi_sendmail.c
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_sendmail.c,v $ * PRODUCTION Revision 1000.1 2004/02/12 21:52:59 gouriano * PRODUCTION PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.22 * PRODUCTION * =========================================================================== *//* $Id: ncbi_sendmail.c,v 1000.1 2004/02/12 21:52:59 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anton Lavrentiev * * File Description: * Send mail * */#include "ncbi_ansi_ext.h"#include "ncbi_priv.h"#include <connect/ncbi_sendmail.h>#include <connect/ncbi_socket.h>#include <ctype.h>#include <stdlib.h>#ifdef NCBI_OS_UNIX#include <pwd.h>#include <unistd.h>#endif#ifdef NCBI_CXX_TOOLKIT#define NCBI_SENDMAIL_TOOLKIT "C++"#else#define NCBI_SENDMAIL_TOOLKIT "C"#endif#define MX_MAGIC_NUMBER 0xBA8ADEDA#define MX_CRLF "\r\n"#define SMTP_READERR -1 /* Error reading from socket */#define SMTP_REPLYERR -2 /* Error reading reply prefix */#define SMTP_BADCODE -3 /* Reply code doesn't match in lines */#define SMTP_BADREPLY -4 /* Malformed reply text */#define SMTP_NOCODE -5 /* No reply code detected (letters?) */#define SMTP_WRITERR -6 /* Error writing to socket *//* Read SMTP reply from the socket. * Return reply in the buffer provided, * and reply code (positive value) as a return value. * Return a negative code in case of problem (protocol reply * read error or protocol violations). * Return 0 in case of call error. */static int s_SockRead(SOCK sock, char* reply, size_t reply_len){ int/*bool*/ done = 0; size_t n = 0; int code = 0; if (!reply || !reply_len) return 0; do { size_t m = 0; char buf[4]; if (SOCK_Read(sock, buf, 4, &m, eIO_ReadPersist) != eIO_Success) return SMTP_READERR; if (m != 4) return SMTP_REPLYERR; if (buf[3] == '-' || (done = isspace((unsigned char) buf[3]))) { buf[3] = 0; if (!code) { if (!(code = atoi(buf))) return SMTP_NOCODE; } else if (code != atoi(buf)) return SMTP_BADCODE; } else return SMTP_BADREPLY; do { m = 0; if (SOCK_Read(sock,buf,1,&m,eIO_ReadPlain) != eIO_Success || !m) return SMTP_READERR; if (buf[0] != '\r' && n < reply_len) reply[n++] = buf[0]; } while (buf[0] != '\n'); /* At least '\n' should sit in buffer */ assert(n); if (done) reply[n - 1] = 0; else if (n < reply_len) reply[n] = ' '; } while (!done); assert(code); return code;}static int/*bool*/ s_SockReadResponse(SOCK sock, int code, int alt_code, char* buf, size_t buf_size){ int c = s_SockRead(sock, buf, buf_size); if (c <= 0) { const char* message = 0; switch (c) { case SMTP_READERR: message = "Read error"; break; case SMTP_REPLYERR: message = "Error reading reply prefix"; break; case SMTP_BADCODE: message = "Reply code doesn't match in lines"; break; case SMTP_BADREPLY: message = "Malformed reply text"; break; case SMTP_NOCODE: message = "No reply code detected"; break; case SMTP_WRITERR: message = "Write error"; break; default: message = "Unknown error"; break; } assert(message); strncpy0(buf, message, buf_size - 1); } else if (c == code || (alt_code && c == alt_code)) return 1/*success*/; return 0/*failure*/;}static int/*bool*/ s_SockWrite(SOCK sock, const char* buf){ size_t len = strlen(buf); size_t n; if (SOCK_Write(sock, buf, len, &n, eIO_WritePersist) == eIO_Success && n == len) { return 1/*success*/; } return 0/*failure*/;}static char* s_ComposeFrom(char* buf, size_t buf_size){ size_t buf_len, hostname_len;#ifdef NCBI_OS_UNIX /* Get the user login name. FIXME: not MT-safe */ const char* login_name; CORE_LOCK_WRITE; login_name = getlogin(); if (!login_name) { struct passwd* pwd = getpwuid(getuid()); if (!pwd) { if (!(login_name = getenv("USER")) && !(login_name = getenv("LOGNAME"))) { CORE_UNLOCK; return 0; } } else login_name = pwd->pw_name; }#else /* Temporary solution for login name */ const char* login_name = "anonymous";# ifdef NCBI_OS_MSWIN const char* user_name = getenv("USERNAME"); if (user_name) login_name = user_name;# endif#endif strncpy0(buf, login_name, buf_size - 1);#ifdef NCBI_OS_UNIX CORE_UNLOCK;#endif buf_len = strlen(buf); hostname_len = buf_size - buf_len; if (hostname_len-- > 1) { buf[buf_len++] = '@'; SOCK_gethostname(&buf[buf_len], hostname_len); } return buf;}SSendMailInfo* SendMailInfo_Init(SSendMailInfo* info){ if (info) { info->magic_number = MX_MAGIC_NUMBER; info->cc = 0; info->bcc = 0; if (!s_ComposeFrom(info->from, sizeof(info->from))) info->from[0] = 0; info->header = 0; info->body_size = 0; info->mx_host = MX_HOST; info->mx_port = MX_PORT; info->mx_timeout.sec = MX_TIMEOUT; info->mx_timeout.usec = 0; info->mx_no_header = 0/*false*/; } return info;}extern const char* CORE_SendMail(const char* to, const char* subject, const char* body){ return CORE_SendMailEx(to, subject, body, 0);}/* In two macros below the smartest (or, weak-minded?) Sun * C compiler warned about unreachable end-of-loop condition * (well, it thinks "a condition" is there, dumb!), if we * used 'return' right before the end of 'while' statement. * So we now added "check" and "conditional" exit, which makes * the Sun compiler much happier, and less wordy :-) */#define SENDMAIL_RETURN(reason) \ do { \ if (sock) \ SOCK_Close(sock); \ CORE_LOGF(eLOG_Error, ("[SendMail] %s", reason)); \ if (reason/*always true, though, to trick "smart" compiler*/) \ return reason; \ } while (0)#define SENDMAIL_RETURN2(reason, explanation) \ do { \ if (sock) \ SOCK_Close(sock); \ CORE_LOGF(eLOG_Error, ("[SendMail] %s: %s", reason, explanation)); \ if (reason/*always true, though, to trick "smart" compiler*/) \ return reason; \ } while (0)static const char* s_SendRcpt(SOCK sock, const char* to, char buf[], size_t buf_size, const char what[], const char write_error[], const char proto_error[]){ char c; while ((c = *to++) != 0) { char quote = 0; size_t k = 0; if (isspace((unsigned char) c)) continue; while (k < buf_size) { if (quote) { if (c == quote) quote = 0; } else if (c == '"' || c == '<' || c == '\'') { quote = c == '<' ? '>' : c; } else if (c == ',') break; buf[k++] = c == '\t' ? ' ' : c; if (!(c = *to++)) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -