dovecot-2.2: lib-lda: Added new smtp_client_init/deinit() APIs
dovecot at dovecot.org
dovecot at dovecot.org
Fri Apr 25 13:15:53 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/0f9ce0073c8d
changeset: 17266:0f9ce0073c8d
user: Timo Sirainen <tss at iki.fi>
date: Fri Apr 25 15:54:49 2014 +0300
description:
lib-lda: Added new smtp_client_init/deinit() APIs
The new API allows better error handling.
diffstat:
src/lib-lda/smtp-client.c | 88 ++++++++++++++++++++++++++++++++++++++--------
src/lib-lda/smtp-client.h | 8 ++++
2 files changed, 80 insertions(+), 16 deletions(-)
diffs (194 lines):
diff -r eae44873dbc2 -r 0f9ce0073c8d src/lib-lda/smtp-client.c
--- a/src/lib-lda/smtp-client.c Fri Apr 25 15:52:37 2014 +0300
+++ b/src/lib-lda/smtp-client.c Fri Apr 25 15:54:49 2014 +0300
@@ -34,6 +34,8 @@
char *temp_path;
char *destination;
char *return_path;
+ char *error;
+ bool tempfail;
};
static struct smtp_client *smtp_client_devnull(struct ostream **output_r)
@@ -84,7 +86,7 @@
}
static struct smtp_client *
-smtp_client_open_sendmail(const struct lda_settings *set,
+smtp_client_init_sendmail(const struct lda_settings *set,
const char *destination, const char *return_path,
struct ostream **output_r)
{
@@ -147,7 +149,7 @@
}
struct smtp_client *
-smtp_client_open(const struct lda_settings *set, const char *destination,
+smtp_client_init(const struct lda_settings *set, const char *destination,
const char *return_path, struct ostream **output_r)
{
struct smtp_client *client;
@@ -155,7 +157,7 @@
int fd;
if (*set->submission_host == '\0') {
- return smtp_client_open_sendmail(set, destination,
+ return smtp_client_init_sendmail(set, destination,
return_path, output_r);
}
@@ -176,14 +178,14 @@
return client;
}
-static int smtp_client_close_sendmail(struct smtp_client *client)
+static int smtp_client_deinit_sendmail(struct smtp_client *client)
{
int ret = EX_TEMPFAIL, status;
o_stream_destroy(&client->output);
if (client->pid == (pid_t)-1) {
- /* smtp_client_open() failed already */
+ /* smtp_client_init() failed already */
} else if (waitpid(client->pid, &status, 0) < 0)
i_error("waitpid() failed: %m");
else if (WIFEXITED(status)) {
@@ -193,8 +195,8 @@
"exit status %d", ret);
}
} else if (WIFSIGNALED(status)) {
- i_error("Sendmail process terminated abnormally, "
- "signal %d", WTERMSIG(status));
+ i_error("Sendmail process terminated abnormally, signal %d",
+ WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
i_error("Sendmail process stopped, signal %d",
WSTOPSIG(status));
@@ -217,13 +219,24 @@
}
static void
+smtp_client_error(struct smtp_client *smtp_client, const char *error)
+{
+ if (smtp_client->error == NULL) {
+ smtp_client->error = i_strdup_printf("smtp(%s): %s",
+ smtp_client->set->submission_host, error);
+ }
+}
+
+static void
rcpt_to_callback(bool success, const char *reply, void *context)
{
struct smtp_client *smtp_client = context;
if (!success) {
- i_error("smtp(%s): RCPT TO failed: %s",
- smtp_client->set->submission_host, reply);
+ if (reply[0] != '5')
+ smtp_client->tempfail = TRUE;
+ smtp_client_error(smtp_client, t_strdup_printf(
+ "RCPT TO failed: %s", reply));
smtp_client_send_finished(smtp_client);
}
}
@@ -234,8 +247,10 @@
struct smtp_client *smtp_client = context;
if (!success) {
- i_error("smtp(%s): DATA failed: %s",
- smtp_client->set->submission_host, reply);
+ if (reply[0] != '5')
+ smtp_client->tempfail = TRUE;
+ smtp_client_error(smtp_client, t_strdup_printf(
+ "DATA failed: %s", reply));
smtp_client_send_finished(smtp_client);
} else {
smtp_client->success = TRUE;
@@ -298,15 +313,26 @@
if (!smtp_client->finished)
io_loop_run(ioloop);
io_loop_destroy(&ioloop);
- return smtp_client->success ? 0 : -1;
+
+ if (smtp_client->success)
+ return 1;
+ else if (smtp_client->tempfail)
+ return -1;
+ else
+ return 0;
}
-int smtp_client_close(struct smtp_client *client)
+int smtp_client_deinit(struct smtp_client *client, const char **error_r)
{
int ret;
- if (!client->use_smtp)
- return smtp_client_close_sendmail(client);
+ if (!client->use_smtp) {
+ if (smtp_client_deinit_sendmail(client) != 0) {
+ *error_r = "Failed to execute sendmail";
+ return -1;
+ }
+ return 1;
+ }
/* the mail has been written to a file. now actually send it. */
ret = smtp_client_send(client);
@@ -315,6 +341,36 @@
i_free(client->return_path);
i_free(client->destination);
i_free(client->temp_path);
+
+ *error_r = t_strdup(client->error);
+ i_free(client->error);
i_free(client);
- return ret < 0 ? EX_TEMPFAIL : 0;
+ return ret;
}
+
+struct smtp_client *
+smtp_client_open(const struct lda_settings *set, const char *destination,
+ const char *return_path, struct ostream **output_r)
+{
+ return smtp_client_init(set, destination, return_path, output_r);
+}
+
+int smtp_client_close(struct smtp_client *client)
+{
+ const char *error;
+ int ret;
+
+ if (!client->use_smtp)
+ return smtp_client_deinit_sendmail(client);
+
+ ret = smtp_client_deinit(client, &error);
+ if (ret < 0) {
+ i_error("%s", error);
+ return EX_TEMPFAIL;
+ }
+ if (ret == 0) {
+ i_error("%s", error);
+ return EX_NOPERM;
+ }
+ return 0;
+}
diff -r eae44873dbc2 -r 0f9ce0073c8d src/lib-lda/smtp-client.h
--- a/src/lib-lda/smtp-client.h Fri Apr 25 15:52:37 2014 +0300
+++ b/src/lib-lda/smtp-client.h Fri Apr 25 15:54:49 2014 +0300
@@ -4,6 +4,14 @@
#include <stdio.h>
struct smtp_client * ATTR_NULL(3)
+smtp_client_init(const struct lda_settings *set, const char *destination,
+ const char *return_path, struct ostream **output_r);
+/* Returns 1 on success, 0 on permanent failure (e.g. invalid destination),
+ -1 on temporary failure. */
+int smtp_client_deinit(struct smtp_client *client, const char **error_r);
+
+/* FIXME: obsolete API, remove in v2.3: */
+struct smtp_client * ATTR_NULL(3)
smtp_client_open(const struct lda_settings *set, const char *destination,
const char *return_path, struct ostream **output_r);
/* Returns sysexits-compatible return value */
More information about the dovecot-cvs
mailing list