1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 * Copyright (C) 2006-2016 XNeur Team
17 *
18 */
19
20 #include <string.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30 #include <netdb.h>
31
32 #include "log.h"
33
34 #define CMDCOUNT 6
35 char *mail[CMDCOUNT] = { "EHLO xneur.ru\n",
36 "MAIL FROM:xneurlog@xneur.ru\n",
37 "RCPT TO:",
38 "DATA\n",
39 ".\n",
40 "QUIT\n" };
41
42 #define FROM "From: <xneurlog@xneur.ru>\n"
43 #define SUBJ "Subject: Log Archive\n"
44 #define MIME "MIME-Version: 1.0\n"
45 #define CONT_MIX "Content-Type: multipart/mixed; boundary=\"----------D675117161112F6\"\n\n"
46 #define BOUN "------------D675117161112F6\n"
47 #define BOUN_END "------------D675117161112F6--\n\n"
48 #define CONT_TXT "Content-Type: text/plain; charset=utf-8\n\n"
49 #define TEXT "Xneur log in attachment\n\n"
50 #define CONT_APP "Content-Type: application/x-gzip; name=\"%s\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; filename=\"%s\"\n\n"
51
52 #define DEFAULT_BUFLEN 1024
53
encodeblock(unsigned char in[3],unsigned char out[4],int len)54 void encodeblock(unsigned char in[3], unsigned char out[4], int len)
55 {
56 const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57
58 out[0] = cb64[ in[0] >> 2 ];
59 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
60 out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
61 out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
62 }
63
encode_base64(FILE * infile,char * base64text)64 void encode_base64(FILE *infile, char *base64text)
65 {
66 int linesize = 72;
67
68 unsigned char in[3], out[4];
69 int i, j = 0, len, blocksout = 0;
70
71 while (!feof(infile))
72 {
73 len = 0;
74
75 for (i = 0; i < 3; i++)
76 {
77 in[i] = (unsigned char) getc(infile);
78 if (!feof(infile))
79 len++;
80 else
81 in[i] = 0;
82 }
83 if (len)
84 {
85 encodeblock(in, out, len);
86 for (i = 0; i < 4; i++)
87 base64text[j++] = out[i];
88 blocksout++;
89 }
90 if (blocksout >= (linesize/4) || feof(infile))
91 {
92 if (blocksout)
93 base64text[j++] = '\n';
94 blocksout = 0;
95 }
96 }
97 }
98
send_packet(int s,const void * msg,size_t len,int flags)99 static void send_packet(int s, const void *msg, size_t len, int flags)
100 {
101 ssize_t count = send(s, msg, len, flags);
102 if (count == -1)
103 log_message (ERROR, _("Lost the package when sending mail."));
104 }
105
send_mail_with_attach(char * file,char host[],int port,char rcpt[])106 void send_mail_with_attach(char *file, char host[], int port, char rcpt[])
107 {
108 if (host == NULL)
109 return;
110 if (rcpt == NULL)
111 return;
112 if (file == NULL)
113 return;
114
115 int fd, i;
116
117 struct sockaddr_in sock;
118 struct hostent *hp;
119
120 sock.sin_family = AF_INET;
121 //sock.sin_addr.s_addr = inet_addr(host);
122 if (inet_aton(host, &sock.sin_addr) != 1)
123 {
124 hp = gethostbyname(host);
125 if (!hp)
126 {
127 log_message(ERROR, _("Unknown host %s\n"), host);
128 return;
129 }
130 memcpy(&sock.sin_addr, hp->h_addr, 4);
131 }
132 sock.sin_port = htons(port);
133 memset(&sock.sin_zero, '\0', 8);
134
135 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
136 {
137 log_message(ERROR, _("Unable open socket!"));
138 return;
139 }
140
141 if (connect(fd, (struct sockaddr *)&sock, sizeof(struct sockaddr)) == -1)
142 {
143 close(fd);
144 log_message(ERROR, _("Unable to connect to %s"), (char *)inet_ntoa(sock.sin_addr));
145 return;
146 }
147
148 FILE *stream = fopen(file, "rb");
149 if (stream == NULL)
150 {
151 log_message (ERROR, _("Can't open to read file \"%s\""), file);
152 close(fd);
153 return;
154 }
155
156 struct stat sb;
157 if (stat(file, &sb) != 0)
158 {
159 close(fd);
160 fclose(stream);
161 log_message (ERROR, _("Can't get state of file \"%s\""), file);
162 return;
163 }
164
165 if (sb.st_size < 0)
166 {
167 close(fd);
168 fclose(stream);
169 log_message (ERROR, _("Can't get state of file \"%s\""), file);
170 return;
171 }
172
173 do {
174 file = strstr(file, "/");
175 if (file == NULL)
176 {
177 close(fd);
178 fclose(stream);
179 return;
180 }
181 file++;
182 } while (strstr(file, "/") != NULL);
183
184 for (i = 0; i < CMDCOUNT; i++)
185 {
186 send_packet(fd, mail[i], strlen(mail[i]), 0);
187 if (i == 2)
188 {
189 send_packet(fd, rcpt, strlen(rcpt), 0);
190 send_packet(fd, "\n", sizeof(char), 0);
191 }
192 if (i == 3)
193 {
194 send_packet(fd, FROM, strlen(FROM), 0);
195 send_packet(fd, "To: ", 4, 0);
196 send_packet(fd, rcpt, strlen(rcpt), 0);
197 send_packet(fd, "\n", sizeof(char), 0);
198 send_packet(fd, SUBJ, strlen(SUBJ), 0);
199 send_packet(fd, MIME, strlen(MIME), 0);
200 send_packet(fd, CONT_MIX, strlen(CONT_MIX), 0);
201 send_packet(fd, BOUN, strlen(BOUN), 0);
202 send_packet(fd, CONT_TXT, strlen(CONT_TXT), 0);
203 send_packet(fd, TEXT, strlen(TEXT), 0);
204 send_packet(fd, BOUN, strlen(BOUN), 0);
205 char *cont_app = malloc((strlen(CONT_APP)+ 2*strlen(file) + 5) * sizeof(char));
206 sprintf (cont_app, CONT_APP, file, file);
207 send_packet(fd, cont_app, strlen(cont_app), 0);
208 free(cont_app);
209 char *base64text = malloc((sb.st_size*2) * sizeof(char));
210 encode_base64(stream, base64text);
211 send_packet(fd, base64text, strlen(base64text), 0);
212 free(base64text);
213
214 send_packet(fd, BOUN_END, strlen(BOUN_END), 0);
215 }
216 }
217
218 sleep(5);
219 char recvbuf[DEFAULT_BUFLEN];
220 int recvbuflen = DEFAULT_BUFLEN;
221 int result = 0;
222 do {
223 result = recv(fd, recvbuf, recvbuflen, 0);
224 if (result < 0)
225 {
226 close(fd);
227 fclose(stream);
228 log_message (ERROR, _("Mail server return Error %d"), result);
229 return;
230 }
231 recvbuf[result] = '\0';
232 /*if ( result > 0 )
233 log_message (DEBUG, "Mail server return answer:\n%s\n", recvbuf, result);
234 else if ( result == 0 )
235 log_message (ERROR, "Connection closed");
236 else
237 log_message (ERROR, "Connection Error %d", result);*/
238 } while( result > 0 );
239
240 close(fd);
241 fclose(stream);
242 }
243