Aaron Stone wrote:
On Wed, Mar 9, 2005, Paul J Stevens <[EMAIL PROTECTED]> said:
I've also committed this to the 2.0 svn branch. About time we cut a
2.0.4rc1 I suppose. Aaron? We can defer bug #161 to 2.0.5 or even 2.1,
but any guesstimates on #164, perhaps?
Ok, thanks for reminding me. Let's kick #161 because if we haven't started
looking into what crashes the mime parser, now ain't the time. For #164, I
will *right now* put my work-in-progress patch on the bug page. Paul, I
hope you can run with it and get 2.0.4 out the door!
I got it to compile, but I'll have to think a bit about the logic involved here.
--
________________________________________________________________
Paul Stevens [EMAIL PROTECTED]
NET FACILITIES GROUP GPG/PGP: 1024D/11F8CD31
The Netherlands_______________________________________www.nfg.nl
#! /bin/sh /usr/share/dpatch/dpatch-run
## 01_quota.dpatch by <[EMAIL PROTECTED]>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.
@DPATCH@
diff -urNad dbmail-2.0/dsn.c /tmp/dpep.9YzUej/dbmail-2.0/dsn.c
--- dbmail-2.0/dsn.c 2005-03-10 14:43:49.000000000 +0100
+++ /tmp/dpep.9YzUej/dbmail-2.0/dsn.c 2005-03-10 14:44:46.000000000 +0100
@@ -407,10 +407,12 @@
list_freelist(&deliveries->start);
}
-dsn_class_t dsnuser_worstcase_int(int has_2, int has_4, int has_5)
+delivery_status_t dsnuser_worstcase_int(int has_2, int has_4, int has_5, int
has_5_2)
{
dsn_class_t exitcode;
+ /**/
+
/* If only one code, use it. */
if (has_2 && !has_4 && !has_5) /* Only 2 */
exitcode = DSN_CLASS_OK;
@@ -432,15 +434,17 @@
return exitcode;
}
-dsn_class_t dsnuser_worstcase_list(struct list * deliveries)
+delivery_status_t dsnuser_worstcase_list(struct list * deliveries)
{
+ dsn_t dsn;
struct element *tmp;
- int has_2 = 0, has_4 = 0, has_5 = 0;
+ int has_2 = 0, has_4 = 0, has_5 = 0, has_5_2 = 0;
/* Get one reasonable error code for everyone. */
for (tmp = list_getstart(deliveries); tmp != NULL;
tmp = tmp->nextnode) {
- switch (((deliver_to_user_t *) tmp->data)->dsn.class) {
+ delivery_status_t dsn = ((deliver_to_user_t *) tmp->data)->dsn;
+ switch (dsn.class) {
case DSN_CLASS_OK:
/* Success. */
has_2 = 1;
@@ -451,7 +455,10 @@
break;
case DSN_CLASS_FAIL:
/* Permanent failure. */
- has_5 = 1;
+ if (dsn.subject == 2)
+ has_5_2 = 1;
+ else
+ has_5 = 1;
break;
case DSN_CLASS_NONE:
/* Nothing doing. */
@@ -461,5 +468,5 @@
/* If we never made it into the list, all zeroes will
* yield a temporary failure, which is pretty reasonable. */
- return dsnuser_worstcase_int(has_2, has_4, has_5);
+ return dsnuser_worstcase_int(has_2, has_4, has_5, has_5_2);
}
diff -urNad dbmail-2.0/main.c /tmp/dpep.9YzUej/dbmail-2.0/main.c
--- dbmail-2.0/main.c 2005-03-10 14:43:52.000000000 +0100
+++ /tmp/dpep.9YzUej/dbmail-2.0/main.c 2005-03-10 14:44:46.000000000 +0100
@@ -466,8 +466,12 @@
/* If there wasn't already an EX_TEMPFAIL from insert_messages(),
* then see if one of the status flags was marked with an error. */
if (!exitcode) {
+ delivery_status_t final_dsn;
+
/* Get one reasonable error code for everyone. */
- switch (dsnuser_worstcase_list(&dsnusers)) {
+ final_dsn = dsnuser_worstcase_list(&dsnusers);
+
+ switch (final_dsn.class) {
case DSN_CLASS_OK:
exitcode = EX_OK;
break;
@@ -476,7 +480,12 @@
break;
case DSN_CLASS_NONE:
case DSN_CLASS_FAIL:
- exitcode = EX_NOUSER;
+ /* If we're over-quota, say that,
+ * else it's a generic user error. */
+ if (final_dsn.subject = 2)
+ exitcode = EX_CANTCREAT;
+ else
+ exitcode = EX_NOUSER;
break;
}
}
diff -urNad dbmail-2.0/pipe.c /tmp/dpep.9YzUej/dbmail-2.0/pipe.c
--- dbmail-2.0/pipe.c 2005-03-10 14:43:49.000000000 +0100
+++ /tmp/dpep.9YzUej/dbmail-2.0/pipe.c 2005-03-10 14:44:46.000000000 +0100
@@ -554,7 +554,7 @@
for (element = list_getstart(dsnusers); element != NULL;
element = element->nextnode) {
struct element *userid_elem;
- int has_2 = 0, has_4 = 0, has_5 = 0;
+ int has_2 = 0, has_4 = 0, has_5 = 0, has_5_2 = 0;
deliver_to_user_t *delivery =
(deliver_to_user_t *) element->data;
@@ -578,22 +578,28 @@
msgsize, rfcsize,
useridnr,
delivery->mailbox)) {
- case DSN_CLASS_OK:
+ case SORT_SUCCESS:
/* Indicate success. */
trace(TRACE_DEBUG,
"%s, %s: successful sort_and_deliver for
useridnr [%llu]",
__FILE__, __func__, useridnr);
has_2 = 1;
break;
- case DSN_CLASS_FAIL:
+ case SORT_FAILURE:
/* Indicate permanent failure. */
trace(TRACE_ERROR,
"%s, %s: permanent failure
sort_and_deliver for useridnr [%llu]",
__FILE__, __func__, useridnr);
has_5 = 1;
break;
- case DSN_CLASS_TEMP:
- case -1:
+ case SORT_OVER_QUOTA:
+ /* Indicate over quota. */
+ trace(TRACE_ERROR,
+ "%s, %s: temporary failure
sort_and_deliver for useridnr [%llu]",
+ __FILE__, __func__, useridnr);
+ has_5_2 = 1;
+ break;
+ case SORT_WEIRD_ERROR:
default:
/* Assume a temporary failure */
trace(TRACE_ERROR,
@@ -610,7 +616,7 @@
__FILE__, __func__);
} /* from: the useridnr for loop */
- switch (dsnuser_worstcase_int(has_2, has_4, has_5)) {
+ switch (dsnuser_worstcase_int(has_2, has_4, has_5, has_5_2)) {
case DSN_CLASS_OK:
delivery->dsn.class = DSN_CLASS_OK; /* Success. */
delivery->dsn.subject = 1; /* Address related. */
@@ -634,6 +640,11 @@
delivery->dsn.subject = 1; /* Address related. */
delivery->dsn.detail = 1; /* Does not exist. */
break;
+ case DSN_CLASS_QUOTA:
+ delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent
failure. */
+ delivery->dsn.subject = 2; /* Mailbox related. */
+ delivery->dsn.detail = 2; /* Over quota limit. */
+ break;
case DSN_CLASS_NONE:
/* Leave the DSN status at whatever dsnuser_resolve set
it at. */
break;
diff -urNad dbmail-2.0/sort/sort.c /tmp/dpep.9YzUej/dbmail-2.0/sort/sort.c
--- dbmail-2.0/sort/sort.c 2005-03-10 14:43:52.000000000 +0100
+++ /tmp/dpep.9YzUej/dbmail-2.0/sort/sort.c 2005-03-10 14:44:46.000000000
+0100
@@ -111,267 +111,39 @@
if (mailbox == NULL)
mailbox = inbox;
- /* actions is a list of things to do with this message
- * each data pointer in the actions list references
- * a structure like this:
- *
- * typedef sort_action {
- * int method,
- * char *destination,
- * char *message
- * } sort_action_t;
- *
- * Where message is some descriptive text, used
- * primarily for rejection noticed, and where
- * destination is either a mailbox name or a
- * forwarding address, and method is one of these:
- *
- * SA_KEEP,
- * SA_DISCARD,
- * SA_REDIRECT,
- * SA_REJECT,
- * SA_FILEINTO
- * (see RFC 3028 [SIEVE] for details)
- *
- * SA_SIEVE:
- * In addition, this implementation allows for
- * the internel Regex matching to call a Sieve
- * script into action. In this case, the method
- * is SA_SIEVE and the destination is the script's name.
- * Note that Sieve must be enabled in the configuration
- * file or else an error will be generated.
- *
- * In the absence of any valid actions (ie. actions
- * is an empty list, or all attempts at performing the
- * actions fail...) an implicit SA_KEEP is performed,
- * using INBOX as the destination (hardcoded).
- * */
-
- if (list_totalnodes(&actions) > 0) {
- tmp = list_getstart(&actions);
- while (tmp != NULL) {
- /* Try not to think about the structures too hard ;-) */
- switch ((int) ((sort_action_t *) tmp->data)->
- method) {
- case SA_SIEVE:
- {
- /* Run the script specified by
destination and
- * add the resulting list onto the
*end* of the
- * actions list. Note that this is a
deep hack...
- * */
- if ((char *) ((sort_action_t *)
- tmp->data)->
- destination != NULL) {
- struct list localtmplist;
- struct element
- *localtmpelem;
-// if (sortsieve_msgsort(useridnr, header, headersize,
(char *)((sort_action_t *)tmp->data)->destination, localtmplist))
- {
- /* FIXME: This can all
be replaced with some
- * function called
list_append(), if written! */
- /* Fast forward to the
end of the actions list */
- localtmpelem =
- list_getstart
- (&actions);
- while (localtmpelem
- != NULL) {
- localtmpelem
- =
-
localtmpelem->
- nextnode;
- }
- /* And tack on the
start of the Sieve list */
- localtmpelem->
- nextnode =
- list_getstart
- (&localtmplist);
- /* Remeber to increment
the node count, too */
- actions.
- total_nodes +=
- list_totalnodes
- (&localtmplist);
- }
- }
- break;
- }
- case SA_FILEINTO:
- {
- char *fileinto_mailbox =
- (char *) ((sort_action_t *)
- tmp->data)->
- destination;
-
- /* If the action doesn't come with a
mailbox, use the default. */
-
- if (fileinto_mailbox == NULL) {
- /* Cast the const away because
fileinto_mailbox may need to be freed. */
- fileinto_mailbox =
- (char *) mailbox;
- trace(TRACE_MESSAGE,
- "sort_and_deliver():
mailbox not specified, using [%s]",
- fileinto_mailbox);
- }
-
-
- /* Did we fail to create the mailbox? */
- if (db_find_create_mailbox
- (fileinto_mailbox, useridnr,
- &mboxidnr) != 0) {
- /* FIXME: Serious failure
situation! This needs to be
- * passed up the chain to
notify the user, sender, etc.
- * Perhaps we should *force*
the implicit-keep to occur,
- * or give another try at using
INBOX. */
- trace(TRACE_ERROR,
- "sort_and_deliver():
mailbox [%s] not found nor created, message may not have been delivered",
- fileinto_mailbox);
- } else {
- switch (db_copymsg
- (msgidnr, mboxidnr,
- useridnr,
- &newmsgidnr)) {
- case -2:
- /* Couldn't deliver
because the quota has been reached */
- break;
- case -1:
- /* Couldn't deliver
because something something went wrong */
- trace(TRACE_ERROR,
-
"sort_and_deliver(): error copying message to user [%llu]",
- useridnr);
- /* Don't worry about
error conditions.
- * It's annoying if the
message isn't delivered,
- * but as long as
*something* happens it's OK.
- * Otherwise,
actiontaken will be 0 and another
- * delivery attempt
will be made before passing
- * up the error at the
end of the function.
- * */
- break;
- default:
- trace
- (TRACE_MESSAGE,
-
"sort_and_deliver(): message id=%llu, size=%llu is inserted",
- newmsgidnr,
- totalmsgsize);
-
- /* Create a unique ID
for this message;
- * Each message for
each user must have a unique ID!
- * */
- create_unique_id
- (unique_id,
- newmsgidnr);
- db_message_set_unique_id
- (newmsgidnr,
- unique_id);
-
- actiontaken = 1;
- break;
- }
- }
-
- /* If these are not same pointers, then
we need to free. */
- if (fileinto_mailbox != mailbox)
- dm_free(fileinto_mailbox);
-
- break;
- }
- case SA_DISCARD:
- {
- /* Basically do nothing! */
- actiontaken = 1;
- break;
- }
- case SA_REJECT:
- {
- // FIXME: I'm happy with this code, but
it's not quite right...
- // Plus we want to specify a message to
go along with it!
- actiontaken = 1;
- break;
- }
- case SA_REDIRECT:
- {
- char *forward_id;
- struct list targets;
-
- list_init(&targets);
- list_nodeadd(&targets,
- (char
- *) ((sort_action_t *)
- tmp->data)->
- destination,
- strlen((char
- *) ((sort_action_t
*) tmp->data)->destination) + 1);
- dm_free((char *) ((sort_action_t *)
- tmp->data)->
- destination);
-
- /* Put the destination into the targets
list */
- /* The From header will contain... */
- forward_id =
- auth_get_userid(useridnr);
- forward(msgidnr, &targets,
- forward_id, header,
- headersize);
-
- list_freelist(&targets.start);
- dm_free(forward_id);
- actiontaken = 1;
- break;
- }
- /*
- case SA_KEEP:
- default:
- {
- // Don't worry! This is handled by implicit
keep :-)
- break;
- }
- */
- } /* case */
- tmp = tmp->nextnode;
- } /* while */
- list_freelist(&actions.start);
- } /* if */
- else {
- /* Might as well be explicit about this... */
- actiontaken = 0;
- }
+ /* There used to be code that handled the result
+ * actions of a Sieve script. Since it wasn't being
+ * used as of DBMail 2.0.3, I pulled it out.
+ * Aaron Stone, 21 Jan 2005. */
- /* This is that implicit keep I mentioned earlier...
- * If possible, put the message in the specified
- * mailbox, otherwise use INBOX. */
- if (actiontaken == 0) {
- /* Did we fail to create the mailbox? */
- if (db_find_create_mailbox(mailbox, useridnr, &mboxidnr) !=
- 0) {
- /* Serious failure situation! */
+ /* Did we fail to create the mailbox? */
+ if (db_find_create_mailbox(mailbox, useridnr, &mboxidnr) != 0) {
+ /* Serious failure situation! */
+ trace(TRACE_ERROR,
+ "sort_and_deliver(): INBOX not found and could not be
created.");
+ return SORT_FAILURE;
+ } else {
+ switch (db_copymsg(msgidnr, mboxidnr,
+ useridnr, &newmsgidnr)) {
+ case -2:
+ /* Couldn't deliver because the quotum is exceeded. */
+ trace(TRACE_MESSAGE,
+ "%s, %s: error copying message to user [%llu],
maxmail exceeded",
+ __FILE__, __func__, useridnr);
+ return SORT_OVER_QUOTA;
+ case -1:
+ /* Couldn't deliver because something something went
wrong. */
trace(TRACE_ERROR,
- "sort_and_deliver(): INBOX not found");
- } else {
- switch (db_copymsg
- (msgidnr, mboxidnr, useridnr,
- &newmsgidnr)) {
- case -2:
- /* Couldn't deliver because the quotum is
exceeded. */
- trace(TRACE_DEBUG,
- "%s, %s: error copying message to user
[%llu], maxmail exceeded",
- __FILE__, __func__, useridnr);
- break;
- case -1:
- /* Couldn't deliver because something something
went wrong. */
- trace(TRACE_ERROR,
- "%s, %s: error copying message to user
[%llu]",
- __FILE__, __func__, useridnr);
- break;
- default:
- trace(TRACE_MESSAGE,
- "%s, %s: message id=%llu, size=%llu is
inserted",
- __FILE__, __func__, newmsgidnr,
- totalmsgsize);
- actiontaken = 1;
- break;
- }
+ "%s, %s: error copying message to user [%llu]",
+ __FILE__, __func__, useridnr);
+ return SORT_WEIRD_ERROR;
+ default:
+ trace(TRACE_MESSAGE,
+ "%s, %s: message id=%llu, size=%llu is inserted",
+ __FILE__, __func__, newmsgidnr,
+ totalmsgsize);
+ return SORT_SUCCESS;
}
}
-
- if (actiontaken)
- return DSN_CLASS_OK;
- return DSN_CLASS_TEMP;
}
+
diff -urNad dbmail-2.0/sort.h /tmp/dpep.9YzUej/dbmail-2.0/sort.h
--- dbmail-2.0/sort.h 2005-03-10 14:43:49.000000000 +0100
+++ /tmp/dpep.9YzUej/dbmail-2.0/sort.h 2005-03-10 14:44:46.000000000 +0100
@@ -39,7 +39,6 @@
#define SA_REDIRECT 3
#define SA_REJECT 4
#define SA_FILEINTO 5
-#define SA_SIEVE 6
typedef struct sort_action {
int method;
@@ -47,7 +46,14 @@
char *message;
} sort_action_t;
-dsn_class_t sort_and_deliver(u64_t msgidnr,
+typedef enum {
+ SORT_SUCCESS = 0,
+ SORT_OVER_QUOTA,
+ SORT_WEIRD_ERROR,
+ SORT_FAILURE
+} sort_result_t;
+
+sort_result_t sort_and_deliver(u64_t msgidnr,
const char *header, u64_t headersize,
u64_t msgsize, u64_t rfcsize,
u64_t useridnr, const char *mailbox);