masqmail

annotate src/header.c @ 246:4cff8638dd9b

SMTP client: tries EHLO now always first Changed the behavior of the SMTP client. Now always an EHLO greeting is sent, no matter what kind of greeting text the server had sent. If the EHLO failed, an HELO greeting is tried as fall back. This is the behavior RFC 2821 requires (section 3.2). This change will fix setups that were not possible to sent to a server because that requires AUTH but hadn't said ``ESMTP'' in its greeting message. See also: Debian bug #349211 Thanks to Steffen (inne)
author markus schnalke <meillo@marmaro.de>
date Thu, 28 Oct 2010 16:40:02 -0300
parents 3708b655a371
children 55c530a83d51
rev   line source
meillo@0 1 /* MasqMail
meillo@0 2 Copyright (C) 2000 Oliver Kurth
meillo@0 3
meillo@0 4 This program is free software; you can redistribute it and/or modify
meillo@0 5 it under the terms of the GNU General Public License as published by
meillo@0 6 the Free Software Foundation; either version 2 of the License, or
meillo@0 7 (at your option) any later version.
meillo@0 8
meillo@0 9 This program is distributed in the hope that it will be useful,
meillo@0 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
meillo@0 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
meillo@0 12 GNU General Public License for more details.
meillo@0 13
meillo@0 14 You should have received a copy of the GNU General Public License
meillo@0 15 along with this program; if not, write to the Free Software
meillo@0 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
meillo@0 17 */
meillo@0 18 #include "masqmail.h"
meillo@0 19
meillo@10 20 header_name header_names[] = {
meillo@15 21 {"From", HEAD_FROM,},
meillo@15 22 {"Sender", HEAD_SENDER,},
meillo@15 23 {"To", HEAD_TO,},
meillo@15 24 {"Cc", HEAD_CC,},
meillo@15 25 {"Bcc", HEAD_BCC,},
meillo@15 26 {"Date", HEAD_DATE,},
meillo@15 27 {"Message-Id", HEAD_MESSAGE_ID,},
meillo@15 28 {"Reply-To", HEAD_REPLY_TO,},
meillo@15 29 {"Subject", HEAD_SUBJECT,},
meillo@15 30 {"Return-Path", HEAD_RETURN_PATH,},
meillo@15 31 {"Envelope-To", HEAD_ENVELOPE_TO,},
meillo@15 32 {"Received", HEAD_RECEIVED},
meillo@0 33 };
meillo@0 34
meillo@0 35 /* this was borrowed from exim and slightly changed */
meillo@10 36 gchar*
meillo@10 37 rec_timestamp()
meillo@0 38 {
meillo@10 39 static gchar buf[64];
meillo@10 40 int len;
meillo@0 41
meillo@10 42 time_t now = time(NULL);
meillo@10 43 struct tm *t = localtime(&now);
meillo@0 44
meillo@10 45 int diff_hour, diff_min;
meillo@10 46 struct tm local;
meillo@10 47 struct tm *gmt;
meillo@0 48
meillo@10 49 memcpy(&local, t, sizeof(struct tm));
meillo@10 50 gmt = gmtime(&now);
meillo@10 51 diff_min = 60 * (local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
meillo@10 52 if (local.tm_year != gmt->tm_year)
meillo@10 53 diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
meillo@10 54 else if (local.tm_yday != gmt->tm_yday)
meillo@10 55 diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
meillo@10 56 diff_hour = diff_min / 60;
meillo@10 57 diff_min = abs(diff_min - diff_hour * 60);
meillo@0 58
meillo@10 59 len = strftime(buf, sizeof(buf), "%a, ", &local);
meillo@10 60 g_snprintf(buf + len, sizeof(buf) - len, "%02d ", local.tm_mday);
meillo@10 61 len += strlen(buf + len);
meillo@10 62 len += strftime(buf + len, sizeof(buf) - len, "%b %Y %H:%M:%S", &local);
meillo@10 63 g_snprintf(buf + len, sizeof(buf) - len, " %+03d%02d", diff_hour, diff_min);
meillo@10 64
meillo@10 65 return buf;
meillo@0 66 }
meillo@0 67
meillo@0 68 /* finds list of headers matching id
meillo@0 69 if id == HEAD_UNKNOWN and header == NULL finds all unknown headers
meillo@0 70 else finds all headers matching header
meillo@0 71 */
meillo@10 72 GList*
meillo@10 73 find_header(GList * hdr_list, header_id id, gchar * hdr_str)
meillo@0 74 {
meillo@10 75 GList *found_list = NULL;
meillo@10 76 GList *node;
meillo@0 77
meillo@10 78 if ((id != HEAD_UNKNOWN) || (hdr_str == NULL)) {
meillo@10 79 foreach(hdr_list, node) {
meillo@10 80 header *hdr = (header *) (node->data);
meillo@10 81 if (hdr->id == id)
meillo@10 82 found_list = g_list_append(found_list, hdr);
meillo@10 83 }
meillo@10 84 } else {
meillo@10 85 foreach(hdr_list, node) {
meillo@10 86 header *hdr = (header *) (node->data);
meillo@10 87 gchar buf[64], *q = buf, *p = hdr->header;
meillo@10 88
meillo@10 89 while (*p != ':' && q < buf + 63 && *p)
meillo@10 90 *(q++) = *(p++);
meillo@15 91 *q = '\0';
meillo@10 92
meillo@10 93 if (strcasecmp(buf, hdr_str) == 0)
meillo@10 94 found_list = g_list_append(found_list, hdr);
meillo@10 95 }
meillo@10 96 }
meillo@10 97 return found_list;
meillo@0 98 }
meillo@0 99
meillo@10 100 void
meillo@10 101 header_unfold(header * hdr)
meillo@0 102 {
meillo@10 103 gchar *tmp_hdr = g_malloc(strlen(hdr->header));
meillo@10 104 gchar *p = hdr->header, *q = tmp_hdr;
meillo@10 105 gboolean flag = FALSE;
meillo@0 106
meillo@10 107 while (*p) {
meillo@10 108 if (*p != '\n')
meillo@10 109 *(q++) = *p;
meillo@10 110 else
meillo@10 111 flag = TRUE;
meillo@10 112 p++;
meillo@10 113 }
meillo@10 114 *(q++) = '\n';
meillo@0 115
meillo@10 116 if (flag) {
meillo@10 117 gchar *new_hdr;
meillo@0 118
meillo@10 119 g_free(hdr->header);
meillo@10 120 new_hdr = g_strdup(tmp_hdr);
meillo@10 121 g_free(tmp_hdr);
meillo@10 122 hdr->value = new_hdr + (hdr->value - hdr->header);
meillo@10 123 hdr->header = new_hdr;
meillo@10 124 }
meillo@0 125 }
meillo@0 126
meillo@0 127 #define MAX_HDR_LEN 72
meillo@10 128 void
meillo@10 129 header_fold(header * hdr)
meillo@0 130 {
meillo@10 131 gint len = strlen(hdr->header);
meillo@10 132 gchar *p, *q;
meillo@10 133 /* size is probably overestimated, but so we are on the safe side */
meillo@10 134 gchar *tmp_hdr = g_malloc(len + 2 * len / MAX_HDR_LEN);
meillo@0 135
meillo@10 136 p = hdr->header;
meillo@10 137 q = tmp_hdr;
meillo@0 138
meillo@10 139 if (p[len - 1] == '\n')
meillo@15 140 p[len - 1] = '\0';
meillo@0 141
meillo@10 142 while (*p) {
meillo@10 143 gint i, l;
meillo@10 144 gchar *pp;
meillo@0 145
meillo@10 146 /* look forward and find potential break points */
meillo@10 147 i = 0;
meillo@10 148 l = -1;
meillo@10 149 pp = p;
meillo@10 150 while (*pp && (i < MAX_HDR_LEN)) {
meillo@10 151 if ((*pp == ' ') || (*pp == '\t'))
meillo@10 152 l = i;
meillo@10 153 pp++;
meillo@10 154 i++;
meillo@10 155 }
meillo@10 156 if (!*pp)
meillo@10 157 l = pp - p; /* take rest, if EOS found */
meillo@0 158
meillo@10 159 if (l == -1) {
meillo@10 160 /* no potential break point was found within MAX_HDR_LEN so advance further until the next */
meillo@10 161 while (*pp && *pp != ' ' && *pp != '\t') {
meillo@10 162 pp++;
meillo@10 163 i++;
meillo@10 164 }
meillo@10 165 l = i;
meillo@10 166 }
meillo@10 167
meillo@10 168 /* copy */
meillo@10 169 i = 0;
meillo@10 170 while (i < l) {
meillo@10 171 *(q++) = *(p++);
meillo@10 172 i++;
meillo@10 173 }
meillo@10 174 *(q++) = '\n';
meillo@15 175 *(q++) = *(p++); /* this is either space, tab or 0 */
meillo@10 176 }
meillo@10 177 {
meillo@10 178 gchar *new_hdr;
meillo@10 179
meillo@10 180 g_free(hdr->header);
meillo@10 181 new_hdr = g_strdup(tmp_hdr);
meillo@10 182 g_free(tmp_hdr);
meillo@10 183 hdr->value = new_hdr + (hdr->value - hdr->header);
meillo@10 184 hdr->header = new_hdr;
meillo@10 185 }
meillo@0 186 }
meillo@0 187
meillo@10 188 header*
meillo@10 189 create_header(header_id id, gchar * fmt, ...)
meillo@0 190 {
meillo@10 191 gchar *p;
meillo@10 192 header *hdr;
meillo@10 193 va_list args;
meillo@10 194 va_start(args, fmt);
meillo@0 195
meillo@10 196 if ((hdr = g_malloc(sizeof(header)))) {
meillo@0 197
meillo@10 198 hdr->id = id;
meillo@10 199 hdr->header = g_strdup_vprintf(fmt, args);
meillo@10 200 hdr->value = NULL;
meillo@0 201
meillo@10 202 p = hdr->header;
meillo@10 203 while (*p && *p != ':')
meillo@10 204 p++;
meillo@10 205 if (*p)
meillo@10 206 hdr->value = p + 1;
meillo@10 207 }
meillo@0 208
meillo@10 209 va_end(args);
meillo@10 210 return hdr;
meillo@0 211 }
meillo@0 212
meillo@10 213 void
meillo@10 214 destroy_header(header * hdr)
meillo@0 215 {
meillo@10 216 if (hdr) {
meillo@10 217 if (hdr->header)
meillo@10 218 g_free(hdr->header);
meillo@10 219 g_free(hdr);
meillo@10 220 }
meillo@0 221 }
meillo@0 222
meillo@10 223 header*
meillo@10 224 copy_header(header * hdr)
meillo@0 225 {
meillo@10 226 header *new_hdr = NULL;
meillo@0 227
meillo@10 228 if (hdr) {
meillo@10 229 if ((new_hdr = g_malloc(sizeof(header)))) {
meillo@10 230 new_hdr->id = hdr->id;
meillo@10 231 new_hdr->header = g_strdup(hdr->header);
meillo@10 232 new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
meillo@10 233 }
meillo@10 234 }
meillo@10 235 return new_hdr;
meillo@0 236 }
meillo@0 237
meillo@10 238 header*
meillo@10 239 get_header(gchar * line)
meillo@0 240 {
meillo@10 241 gchar *p = line;
meillo@10 242 gchar buf[64], *q = buf;
meillo@10 243 gint i;
meillo@10 244 header *hdr;
meillo@0 245
meillo@10 246 while (*p && (*p != ':') && (q < buf + 63))
meillo@10 247 *(q++) = *(p++);
meillo@15 248 *q = '\0';
meillo@0 249
meillo@10 250 if (*p != ':')
meillo@10 251 return NULL;
meillo@0 252
meillo@10 253 hdr = g_malloc(sizeof(header));
meillo@0 254
meillo@10 255 hdr->value = NULL;
meillo@10 256 p++;
meillo@0 257
meillo@10 258 while (*p && (*p == ' ' || *p == '\t'))
meillo@10 259 p++;
meillo@10 260 hdr->value = p;
meillo@0 261
meillo@10 262 for (i = 0; i < HEAD_NUM_IDS; i++) {
meillo@10 263 if (strcasecmp(header_names[i].header, buf) == 0)
meillo@10 264 break;
meillo@10 265 }
meillo@10 266 hdr->id = (header_id) i;
meillo@10 267 hdr->header = g_strdup(line);
meillo@10 268 hdr->value = hdr->header + (hdr->value - line);
meillo@10 269
meillo@235 270 DEBUG(4) debugf("header: %d = %s", hdr->id, hdr->header);
meillo@10 271
meillo@10 272 return hdr;
meillo@0 273 }