masqmail-0.2

annotate src/message.c @ 171:349518b940db

added support for STARTTLS wrappers added the route config option `instant_helo' which causes masqmail, as SMTP client, not to wait for the server's 220 greeting. Instead if says EHLO right at once. You'll need this for STARTTLS wrappers that usually eat the greeting line.
author meillo@marmaro.de
date Thu, 22 Jul 2010 23:30:05 +0200
parents 71ce3a1568e9
children 087e99c7702a
rev   line source
meillo@0 1 /* MasqMail
meillo@0 2 Copyright (C) 1999-2001 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
meillo@0 19 #include "masqmail.h"
meillo@0 20
meillo@10 21 message*
meillo@10 22 create_message()
meillo@0 23 {
meillo@10 24 message *msg = (message *) g_malloc(sizeof(message));
meillo@10 25 if (msg) {
meillo@10 26 memset(msg, 0, sizeof(message));
meillo@10 27 msg->data_size = -1;
meillo@10 28 }
meillo@10 29 return msg;
meillo@0 30 }
meillo@0 31
meillo@118 32 /*
meillo@118 33 This function is currently (0.2.24) only used for client side SMTP
meillo@118 34 SIZE support (RFC 1870). The flag is_smtp is always true therefore.
meillo@118 35
meillo@118 36 Their definition of the message size in RFC 1870 is:
meillo@118 37
meillo@118 38 The message size is defined as the number of octets, including
meillo@118 39 CR-LF pairs, but not the SMTP DATA command's terminating dot
meillo@118 40 or doubled quoting dots, to be transmitted by the SMTP client
meillo@118 41 after receiving reply code 354 to the DATA command.
meillo@118 42
meillo@118 43 l_cnt (line count) covers '\r' characters which are not present in
meillo@118 44 masqmail's internal format. Dots are also not stuffed in the
meillo@118 45 internal format. Dot-stuffing is ignored in the size.
meillo@118 46 */
meillo@10 47 gint
meillo@10 48 msg_calc_size(message * msg, gboolean is_smtp)
meillo@0 49 {
meillo@10 50 GList *node;
meillo@118 51 gint l_cnt = 0; /* line count (we need to add so many '\r' for SMTP) */
meillo@118 52 gint c_cnt = 0; /* character count */
meillo@0 53
meillo@118 54 /* message header size */
meillo@10 55 if (msg->hdr_list) {
meillo@10 56 for (node = g_list_first(msg->hdr_list); node; node = g_list_next(node)) {
meillo@10 57 if (node->data) {
meillo@10 58 header *hdr = (header *) (node->data);
meillo@10 59 if (hdr->header) {
meillo@10 60 char *p = hdr->header;
meillo@10 61 while (*p) {
meillo@10 62 if (*p++ == '\n')
meillo@10 63 l_cnt++;
meillo@10 64 c_cnt++;
meillo@10 65 }
meillo@10 66 }
meillo@10 67 }
meillo@10 68 }
meillo@0 69 }
meillo@0 70
meillo@10 71 /* empty line separating headers from data: */
meillo@10 72 c_cnt++;
meillo@10 73 l_cnt++;
meillo@0 74
meillo@118 75 /* message data size */
meillo@10 76 if (msg->data_list) {
meillo@10 77 for (node = g_list_first(msg->data_list); node; node = g_list_next(node)) {
meillo@10 78 if (node->data) {
meillo@10 79 char *p = node->data;
meillo@10 80 while (*p) {
meillo@10 81 if (*p++ == '\n')
meillo@10 82 l_cnt++;
meillo@10 83 c_cnt++;
meillo@10 84 }
meillo@10 85 }
meillo@10 86 }
meillo@0 87 }
meillo@0 88
meillo@10 89 return is_smtp ? c_cnt + l_cnt : c_cnt;
meillo@0 90 }
meillo@0 91
meillo@10 92 void
meillo@10 93 msg_free_data(message * msg)
meillo@0 94 {
meillo@10 95 GList *node;
meillo@0 96
meillo@10 97 if (msg->data_list) {
meillo@10 98 for (node = g_list_first(msg->data_list); node; node = g_list_next(node)) {
meillo@10 99 if (node->data)
meillo@10 100 g_free(node->data);
meillo@10 101 }
meillo@10 102 g_list_free(msg->data_list);
meillo@10 103 msg->data_list = NULL;
meillo@10 104 }
meillo@0 105 }
meillo@0 106
meillo@10 107 void
meillo@10 108 destroy_message(message * msg)
meillo@0 109 {
meillo@10 110 GList *node;
meillo@0 111
meillo@81 112 if (!msg) {
meillo@81 113 return;
meillo@81 114 }
meillo@81 115
meillo@10 116 if (msg->uid)
meillo@10 117 g_free(msg->uid);
meillo@10 118 if (msg->ident)
meillo@10 119 g_free(msg->ident);
meillo@10 120 if (msg->return_path)
meillo@10 121 g_free(msg->return_path);
meillo@0 122
meillo@10 123 if (msg->rcpt_list) {
meillo@10 124 for (node = g_list_first(msg->rcpt_list); node; node = g_list_next(node)) {
meillo@10 125 if (node->data)
meillo@10 126 g_free(node->data);
meillo@10 127 }
meillo@10 128 g_list_free(msg->rcpt_list);
meillo@10 129 }
meillo@10 130 if (msg->hdr_list) {
meillo@10 131 for (node = g_list_first(msg->hdr_list); node; node = g_list_next(node)) {
meillo@10 132 if (node->data) {
meillo@10 133 header *hdr = (header *) (node->data);
meillo@10 134 if (hdr->header)
meillo@10 135 g_free(hdr->header);
meillo@10 136 g_free(node->data);
meillo@10 137 }
meillo@10 138 }
meillo@10 139 g_list_free(msg->hdr_list);
meillo@10 140 }
meillo@0 141
meillo@10 142 if (msg->full_sender_name)
meillo@10 143 g_free(msg->full_sender_name);
meillo@0 144
meillo@10 145 msg_free_data(msg);
meillo@0 146
meillo@10 147 g_free(msg);
meillo@0 148 }
meillo@0 149
meillo@10 150 void
meillo@10 151 destroy_msg_list(GList * msg_list)
meillo@0 152 {
meillo@10 153 GList *msg_node;
meillo@0 154
meillo@10 155 foreach(msg_list, msg_node) {
meillo@10 156 message *msg = (message *) (msg_node->data);
meillo@10 157 destroy_message(msg);
meillo@10 158 }
meillo@10 159 g_list_free(msg_list);
meillo@0 160 }
meillo@0 161
meillo@10 162 msg_out*
meillo@10 163 create_msg_out(message * msg)
meillo@0 164 {
meillo@10 165 msg_out *msgout = NULL;
meillo@0 166
meillo@10 167 msgout = g_malloc(sizeof(msg_out));
meillo@10 168 if (msgout) {
meillo@10 169 msgout->msg = msg;
meillo@10 170 msgout->return_path = NULL;
meillo@10 171 msgout->rcpt_list = NULL;
meillo@10 172
meillo@10 173 msgout->hdr_list = NULL;
meillo@10 174 msgout->xtra_hdr_list = NULL;
meillo@10 175 }
meillo@10 176 return msgout;
meillo@0 177 }
meillo@0 178
meillo@10 179 msg_out*
meillo@10 180 clone_msg_out(msg_out * msgout_orig)
meillo@0 181 {
meillo@10 182 if (msgout_orig) {
meillo@10 183 msg_out *msgout = create_msg_out(msgout_orig->msg);
meillo@10 184 if (msgout) {
meillo@10 185 msgout->msg = msgout_orig->msg;
meillo@10 186 if (msgout_orig->return_path)
meillo@10 187 msgout->return_path = copy_address(msgout_orig->return_path);
meillo@10 188 if (msgout_orig->hdr_list)
meillo@10 189 msgout->hdr_list = g_list_copy(msgout_orig->hdr_list);
meillo@10 190 /* FIXME: if this lives longer than the original
meillo@10 191 and we access one of the xtra hdrs, we will segfault
meillo@10 192 or cause some weird bugs: */
meillo@10 193 msgout->xtra_hdr_list = NULL;
meillo@10 194 if (msgout_orig->rcpt_list)
meillo@10 195 msgout->rcpt_list = g_list_copy(msgout_orig->rcpt_list);
meillo@10 196 }
meillo@10 197 return msgout;
meillo@10 198 }
meillo@10 199 return NULL;
meillo@0 200 }
meillo@0 201
meillo@10 202 GList*
meillo@10 203 create_msg_out_list(GList * msg_list)
meillo@0 204 {
meillo@10 205 GList *msgout_list = NULL;
meillo@10 206 GList *msg_node;
meillo@0 207
meillo@10 208 foreach(msg_list, msg_node) {
meillo@10 209 message *msg = (message *) (msg_node->data);
meillo@10 210 msgout_list = g_list_append(msgout_list, create_msg_out(msg));
meillo@10 211 }
meillo@10 212 return msgout_list;
meillo@0 213 }
meillo@0 214
meillo@10 215 void
meillo@10 216 destroy_msg_out(msg_out * msgout)
meillo@0 217 {
meillo@10 218 if (msgout) {
meillo@10 219 if (msgout->return_path)
meillo@10 220 destroy_address(msgout->return_path);
meillo@10 221 if (msgout->hdr_list)
meillo@10 222 g_list_free(msgout->hdr_list);
meillo@10 223 if (msgout->xtra_hdr_list) {
meillo@10 224 GList *hdr_node;
meillo@10 225 foreach(msgout->xtra_hdr_list, hdr_node) {
meillo@10 226 header *hdr = (header *) (hdr_node->data);
meillo@10 227 destroy_header(hdr);
meillo@10 228 }
meillo@10 229 g_list_free(msgout->xtra_hdr_list);
meillo@10 230 }
meillo@10 231 g_free(msgout);
meillo@10 232 }
meillo@0 233 }
meillo@0 234
meillo@10 235 void
meillo@10 236 destroy_msg_out_list(GList * msgout_list)
meillo@0 237 {
meillo@10 238 GList *msgout_node;
meillo@0 239
meillo@10 240 foreach(msgout_list, msgout_node) {
meillo@10 241 msg_out *msgout = (msg_out *) (msgout_node->data);
meillo@10 242 destroy_msg_out(msgout);
meillo@10 243 }
meillo@10 244 g_list_free(msgout_list);
meillo@0 245 }