3 #include <auth-client.h>
6 static char authpass[STRING] = "";
13 #define MSGFAIL(msg) \
15 mutt_error("%s", msg); \
18 #define LIBCFAIL(msg) \
20 mutt_error("%s: %s", msg, strerror(errno)); \
23 #define SMTPFAIL(msg) \
25 _mutt_libesmtp_perror(msg); \
30 * _mutt_libesmtp_ensure_init
31 * Make sure the libESMTP support in mutt is initialized at some time.
34 _mutt_libesmtp_ensure_init()
36 static int libesmtp_init = 0;
46 * _mutt_libesmtp_perror
47 * Prints 'msg', a colon, and then a string representation of the
48 * libesmtp errno as a mutt error.
51 _mutt_libesmtp_perror(const char* msg)
55 mutt_error("%s: %s", msg, smtp_strerror(smtp_errno(), buf, sizeof(buf)));
59 * _mutt_libesmtp_add_recipients
60 * Adds every address in 'addr' as a recipient to the smtp message
61 * 'message'. Note that this does not mean that they will necessarily
62 * show up in the mail headers (e.g., when bcc'ing). Returns 0 upon
63 * success, -1 upon failure (and prints an error message).
65 * Very similar to sendlib.c::add_args
68 _mutt_libesmtp_add_recipients(smtp_message_t message, ADDRESS *addr)
72 for (; addr; addr = addr->next) {
73 /* weed out group mailboxes, since those are for display only */
74 if (addr->mailbox && !addr->group) {
75 if (!smtp_add_recipient(message, addr->mailbox))
76 SMTPFAIL("smtp_add_recipient");
85 _mutt_libesmtp_auth_interact(auth_client_request_t request,
86 char **result, int fields, void *arg)
90 for (i = 0; i < fields; i++) {
91 if (request[i].flags & AUTH_USER) {
92 result[i] = SmtpAuthUser;
93 } else if (request[i].flags & AUTH_PASS) {
95 result[i] = SmtpAuthPass;
97 if (authpass[0] == '\0') {
100 snprintf(prompt, sizeof(prompt), "%s%s: ", request[i].prompt,
101 (request[i].flags & AUTH_CLEARTEXT) ? " (not encrypted)" : "");
102 mutt_get_password(prompt, authpass, sizeof(authpass));
104 result[i] = authpass;
115 _mutt_libesmtp_messagefp_cb(void **buf, int *len, void *arg)
120 *buf = malloc(BUFLEN);
127 if (fgets(*buf, BUFLEN - 2, (FILE*) arg) == NULL) {
130 char* p = strchr(*buf, '\0');
132 if (p[-1] == '\n' && p[-2] != '\r') {
133 strcpy(p - 1, "\r\n");
136 octets = p - (char*) *buf;
144 * mutt_invoke_libesmtp
145 * Sends a mail message to the provided recipients using libesmtp.
146 * Returns 0 upon success, -1 upon failure (and prints an error
150 mutt_invoke_libesmtp(ADDRESS *from, /* the sender */
151 ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */
152 const char *msg, /* file containing message */
153 int eightbit) /* message contains 8bit chars */
155 int ret = 0; /* return value, default = success */
156 smtp_session_t session;
157 smtp_message_t message;
158 char* hostportstr = NULL;
161 auth_context_t authctx = NULL;
162 const smtp_status_t* status;
164 _mutt_libesmtp_ensure_init();
166 if ((session = smtp_create_session()) == NULL)
167 SMTPFAIL("smtp_create_session");
169 /* Create hostname:port string and tell libesmtp */
170 /* len = SmtpHost len + colon + max port (65536 => 5 chars) + terminator */
171 hostportlen = strlen(SmtpHost) + 7;
172 hostportstr = safe_malloc(hostportlen);
173 snprintf(hostportstr, hostportlen, "%s:%d", SmtpHost, SmtpPort);
174 if (!smtp_set_server(session, hostportstr))
175 SMTPFAIL("smtp_set_server");
178 if ((authctx = auth_create_context()) == NULL)
179 MSGFAIL("auth_create_context failed");
180 auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0);
181 auth_set_interact_cb(authctx, _mutt_libesmtp_auth_interact, NULL);
183 if (!smtp_auth_set_context(session, authctx))
184 SMTPFAIL("smtp_auth_set_context");
187 if ((message = smtp_add_message(session)) == NULL)
188 SMTPFAIL("smtp_add_message");
189 /* Initialize envelope sender */
190 if (!smtp_set_reverse_path(message, from->mailbox))
191 SMTPFAIL("smtp_set_reverse_path");
193 if ((fp = fopen(msg, "r")) == NULL)
195 if (!smtp_set_messagecb(message, _mutt_libesmtp_messagefp_cb, fp))
196 SMTPFAIL("smtp_set_messagecb");
197 if (_mutt_libesmtp_add_recipients(message, to))
199 if (_mutt_libesmtp_add_recipients(message, cc))
201 if (_mutt_libesmtp_add_recipients(message, bcc))
203 if (!smtp_start_session(session))
204 SMTPFAIL("smtp_start_session");
206 status = smtp_message_transfer_status(message);
207 if (status->code < 200 || status->code > 299) {
209 snprintf(buf, sizeof(buf), "SMTP error while sending: %d %s", status->code, status->text);
216 if (hostportstr != NULL)
219 smtp_destroy_session(session);
221 auth_destroy_context(authctx);
223 /* Forget user-entered SMTP AUTH password if send fails */