74 |
|
|
75 |
/* ------------------------------------------------------- Private variables */ |
/* ------------------------------------------------------- Private variables */ |
76 |
|
|
77 |
|
typedef struct { |
78 |
static char *server; |
Socket_T socket; |
79 |
static sigjmp_buf error; |
sigjmp_buf error; |
80 |
|
const char *server; |
81 |
|
} SendMail_T; |
82 |
|
|
83 |
|
|
84 |
/* -------------------------------------------------------------- Prototypes */ |
/* -------------------------------------------------------------- Prototypes */ |
85 |
|
|
86 |
|
|
87 |
static void do_status(Socket_T S); |
static void do_status(SendMail_T *S); |
88 |
static void do_send(Socket_T S, const char *, ...); |
static void do_send(SendMail_T *S, const char *, ...); |
89 |
|
|
90 |
|
|
91 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
98 |
void sendmail(Mail_T mail) { |
void sendmail(Mail_T mail) { |
99 |
|
|
100 |
Mail_T m; |
Mail_T m; |
101 |
Socket_T S; |
SendMail_T S; |
102 |
char localhost[STRLEN]; |
char localhost[STRLEN]; |
103 |
char *now = get_RFC822date(NULL); |
char *now = get_RFC822date(NULL); |
104 |
|
|
105 |
ASSERT(mail); |
ASSERT(mail); |
106 |
|
|
107 |
server= Run.mailserver?Run.mailserver:LOCALHOST; |
S.server= Run.mailserver?Run.mailserver:LOCALHOST; |
108 |
|
|
109 |
if(gethostname(localhost, sizeof(localhost)) < 0) { |
if(gethostname(localhost, sizeof(localhost)) < 0) { |
110 |
snprintf(localhost, STRLEN, LOCALHOST); |
snprintf(localhost, STRLEN, LOCALHOST); |
111 |
} |
} |
112 |
|
|
113 |
S= socket_new(server, SMTP_PORT, SOCKET_TCP, FALSE); |
S.socket= socket_new(S.server, SMTP_PORT, SOCKET_TCP, FALSE); |
114 |
if(!S) { |
if(!S.socket) { |
115 |
log("Cannot open a connection to the mailserver '%s' -- %s\n", |
log("Cannot open a connection to the mailserver '%s' -- %s\n", |
116 |
server, STRERROR); |
S.server, STRERROR); |
117 |
goto exit; |
goto exit; |
118 |
} |
} |
119 |
|
|
120 |
if(sigsetjmp(error, TRUE)) { |
if(sigsetjmp(S.error, TRUE)) { |
121 |
goto exit; |
goto exit; |
122 |
} |
} |
123 |
|
|
124 |
do_status(S); |
do_status(&S); |
125 |
do_send(S, "HELO %s\r\n", localhost); |
do_send(&S, "HELO %s\r\n", localhost); |
126 |
do_status(S); |
do_status(&S); |
127 |
|
|
128 |
for(m= mail; m; m= m->next) { |
for(m= mail; m; m= m->next) { |
129 |
|
|
130 |
do_send(S, "MAIL FROM: <%s>\r\n", m->from); |
do_send(&S, "MAIL FROM: <%s>\r\n", m->from); |
131 |
do_status(S); |
do_status(&S); |
132 |
do_send(S, "RCPT TO: <%s>\r\n", m->to); |
do_send(&S, "RCPT TO: <%s>\r\n", m->to); |
133 |
do_status(S); |
do_status(&S); |
134 |
do_send(S, "DATA\r\n"); |
do_send(&S, "DATA\r\n"); |
135 |
do_status(S); |
do_status(&S); |
136 |
do_send(S, "From: %s\r\n", m->from); |
do_send(&S, "From: %s\r\n", m->from); |
137 |
do_send(S, "To: %s\r\n", m->to); |
do_send(&S, "To: %s\r\n", m->to); |
138 |
do_send(S, "Subject: %s\r\n", m->subject); |
do_send(&S, "Subject: %s\r\n", m->subject); |
139 |
do_send(S, "Date: %s\r\n", now); |
do_send(&S, "Date: %s\r\n", now); |
140 |
do_send(S, "X-Mailer: %s %s\r\n", prog, VERSION); |
do_send(&S, "X-Mailer: %s %s\r\n", prog, VERSION); |
141 |
do_send(S, "Mime-Version: 1.0\r\n"); |
do_send(&S, "Mime-Version: 1.0\r\n"); |
142 |
do_send(S, "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"); |
do_send(&S, "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"); |
143 |
do_send(S, "Content-Transfer-Encoding: quoted-printable\r\n"); |
do_send(&S, "Content-Transfer-Encoding: quoted-printable\r\n"); |
144 |
do_send(S, "\r\n"); |
do_send(&S, "\r\n"); |
145 |
do_send(S, "%s\r\n", m->message); |
do_send(&S, "%s\r\n", m->message); |
146 |
if(m->opt_message) { |
if(m->opt_message) { |
147 |
do_send(S, "%s\r\n", m->opt_message); |
do_send(&S, "%s\r\n", m->opt_message); |
148 |
} |
} |
149 |
do_send(S, ".\r\n"); |
do_send(&S, ".\r\n"); |
150 |
do_status(S); |
do_status(&S); |
151 |
|
|
152 |
} |
} |
153 |
|
|
154 |
do_send(S, "QUIT\r\n"); |
do_send(&S, "QUIT\r\n"); |
155 |
|
|
156 |
exit: |
exit: |
157 |
free(now); |
free(now); |
158 |
if(S) { |
if(S.socket) { |
159 |
socket_free(&S); |
socket_free(&S.socket); |
160 |
} |
} |
161 |
|
|
162 |
} |
} |
165 |
/* ----------------------------------------------------------------- Private */ |
/* ----------------------------------------------------------------- Private */ |
166 |
|
|
167 |
|
|
168 |
void do_send(Socket_T S, const char *format, ...) { |
void do_send(SendMail_T *S, const char *format, ...) { |
169 |
|
|
170 |
va_list ap; |
va_list ap; |
171 |
char msg[2048]; |
char msg[2048]; |
174 |
vsnprintf(msg, 2048, format, ap); |
vsnprintf(msg, 2048, format, ap); |
175 |
va_end(ap); |
va_end(ap); |
176 |
|
|
177 |
if(socket_write(S, msg, strlen(msg)) <= 0) { |
if(socket_write(S->socket, msg, strlen(msg)) <= 0) { |
178 |
|
|
179 |
log("Sendmail: error sending data to the server '%s' -- %s\n", |
log("Sendmail: error sending data to the server '%s' -- %s\n", |
180 |
server, STRERROR); |
S->server, STRERROR); |
181 |
siglongjmp(error, TRUE); |
siglongjmp(S->error, TRUE); |
182 |
|
|
183 |
} |
} |
184 |
|
|
185 |
} |
} |
186 |
|
|
187 |
|
|
188 |
static void do_status(Socket_T S) { |
static void do_status(SendMail_T *S) { |
189 |
|
|
190 |
int status; |
int status; |
191 |
char buf[STRLEN]; |
char buf[STRLEN]; |
192 |
|
|
193 |
if(socket_read(S, buf, sizeof(buf)) <= 0) { |
if(socket_read(S->socket, buf, sizeof(buf)) <= 0) { |
194 |
|
|
195 |
log("Sendmail: error receiving data from the mailserver '%s' -- %s\n", |
log("Sendmail: error receiving data from the mailserver '%s' -- %s\n", |
196 |
server, STRERROR); |
S->server, STRERROR); |
197 |
siglongjmp(error, TRUE); |
siglongjmp(S->error, TRUE); |
198 |
|
|
199 |
} |
} |
200 |
|
|
204 |
if(status >= 400) { |
if(status >= 400) { |
205 |
|
|
206 |
log("Sendmail error: %s\n", buf); |
log("Sendmail error: %s\n", buf); |
207 |
siglongjmp(error, TRUE); |
siglongjmp(S->error, TRUE); |
208 |
|
|
209 |
} |
} |
210 |
|
|