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.
33 static void _mutt_libesmtp_ensure_init ()
35 static int libesmtp_init = 0;
45 * _mutt_libesmtp_perror
46 * Prints 'msg', a colon, and then a string representation of the
47 * libesmtp errno as a mutt error.
49 static void _mutt_libesmtp_perror (const char *msg)
53 mutt_error ("%s: %s", msg,
54 smtp_strerror (smtp_errno (), buf, sizeof (buf)));
58 * _mutt_libesmtp_add_recipients
59 * Adds every address in 'addr' as a recipient to the smtp message
60 * 'message'. Note that this does not mean that they will necessarily
61 * show up in the mail headers (e.g., when bcc'ing). Returns 0 upon
62 * success, -1 upon failure (and prints an error message).
64 * Very similar to sendlib.c::add_args
67 _mutt_libesmtp_add_recipients (smtp_message_t message, ADDRESS * addr)
71 for (; addr; addr = addr->next) {
72 /* weed out group mailboxes, since those are for display only */
73 if (addr->mailbox && !addr->group) {
74 if (!smtp_add_recipient (message, addr->mailbox))
75 SMTPFAIL ("smtp_add_recipient");
84 _mutt_libesmtp_auth_interact (auth_client_request_t request,
85 char **result, int fields, void *arg)
89 for (i = 0; i < fields; i++) {
90 if (request[i].flags & AUTH_USER) {
91 result[i] = SmtpAuthUser;
93 else if (request[i].flags & AUTH_PASS) {
95 result[i] = SmtpAuthPass;
98 if (authpass[0] == '\0') {
101 snprintf (prompt, sizeof (prompt), "%s%s: ", request[i].prompt,
103 flags & AUTH_CLEARTEXT) ? " (not encrypted)" : "");
104 mutt_get_password (prompt, authpass, sizeof (authpass));
106 result[i] = authpass;
116 static const char *_mutt_libesmtp_messagefp_cb (void **buf, int *len,
122 *buf = malloc (BUFLEN);
125 rewind ((FILE *) arg);
129 if (fgets (*buf, BUFLEN - 2, (FILE *) arg) == NULL) {
133 char *p = strchr (*buf, '\0');
135 if (p[-1] == '\n' && p[-2] != '\r') {
136 strcpy (p - 1, "\r\n");
139 octets = p - (char *) *buf;
147 * mutt_invoke_libesmtp
148 * Sends a mail message to the provided recipients using libesmtp.
149 * Returns 0 upon success, -1 upon failure (and prints an error
152 int mutt_invoke_libesmtp (ADDRESS * from, /* the sender */
153 ADDRESS * to, ADDRESS * cc, ADDRESS * bcc, /* recips */
154 const char *msg, /* file containing message */
156 { /* message contains 8bit chars */
157 int ret = 0; /* return value, default = success */
158 smtp_session_t session;
159 smtp_message_t message;
160 char *hostportstr = NULL;
163 auth_context_t authctx = NULL;
164 const smtp_status_t *status;
166 _mutt_libesmtp_ensure_init ();
168 if ((session = smtp_create_session ()) == NULL)
169 SMTPFAIL ("smtp_create_session");
171 /* Create hostname:port string and tell libesmtp */
172 /* len = SmtpHost len + colon + max port (65536 => 5 chars) + terminator */
173 hostportlen = strlen (SmtpHost) + 7;
174 hostportstr = safe_malloc (hostportlen);
175 snprintf (hostportstr, hostportlen, "%s:%d", SmtpHost, SmtpPort);
176 if (!smtp_set_server (session, hostportstr))
177 SMTPFAIL ("smtp_set_server");
180 if ((authctx = auth_create_context ()) == NULL)
181 MSGFAIL ("auth_create_context failed");
182 auth_set_mechanism_flags (authctx, AUTH_PLUGIN_PLAIN, 0);
183 auth_set_interact_cb (authctx, _mutt_libesmtp_auth_interact, NULL);
185 if (!smtp_auth_set_context (session, authctx))
186 SMTPFAIL ("smtp_auth_set_context");
189 if ((message = smtp_add_message (session)) == NULL)
190 SMTPFAIL ("smtp_add_message");
191 /* Initialize envelope sender */
192 if (!smtp_set_reverse_path (message, from->mailbox))
193 SMTPFAIL ("smtp_set_reverse_path");
195 if ((fp = fopen (msg, "r")) == NULL)
197 if (!smtp_set_messagecb (message, _mutt_libesmtp_messagefp_cb, fp))
198 SMTPFAIL ("smtp_set_messagecb");
199 if (_mutt_libesmtp_add_recipients (message, to))
201 if (_mutt_libesmtp_add_recipients (message, cc))
203 if (_mutt_libesmtp_add_recipients (message, bcc))
205 if (!smtp_start_session (session))
206 SMTPFAIL ("smtp_start_session");
208 status = smtp_message_transfer_status (message);
209 if (status->code < 200 || status->code > 299) {
212 snprintf (buf, sizeof (buf), "SMTP error while sending: %d %s",
213 status->code, status->text);
220 if (hostportstr != NULL)
223 smtp_destroy_session (session);
225 auth_destroy_context (authctx);
227 /* Forget user-entered SMTP AUTH password if send fails */