Rt-mailgate issue: Empty Tickets created if Attachment insert fails

Hi, I’m currently working with a RT 3 instance and I’ve found that some
Tickets could be created with missing content under specific situations.
This is my scenario:

  • RT 3.8.7 runnig on RHEL5 with perl 5.8.8
  • Oracle 10g database
  • External mail server and fetchmail to recover emails

This RT instance is quite special, we recive a lot of spam (we are working
to fix it) and the database grows quickly. During working days our
monitoring agents alert us about reaching database space limit, but if this
happen on weekend, nobody extends de DB until Monday.
Because of Spam we have configured fetchmail with “no keep” option, so if
Ticket creation fails and fetchmail does not recieve an error return code
the information of the email is lost.
I know that this are a lot of “special situations” but I think that
rt-mailgate should return non zero result when RT couldn’t create the Ticket
correctly.
I haven’t try to reproduce with other databases than Oracle, but I’ve
reproduce this behavior on two different Oracle instances
This are the steps to reproduce the issue:

When rt database tablesapce is full, fetchmail try to recover an email (with
an attachment or an html email).
Ticket is created but we end up with no attach or no text if email was html.
Fetchmail recive a 0 ret code and erase email from server.

I’ve attach the rt log when attachment insert fails.

I don’t know if this is a bug or that’s the way it’s supposed to work, but
we can’t loose the email information.
If this is a bug, I think that could be generated by the scope of the
variable $id in this code (Attachment_Overlay line 140)

# If a message has no bodyhandle, that means that it has subparts (or

appears to)
# and we should act accordingly.
unless ( defined $Attachment->bodyhandle ) {
my ($id) = $self->SUPER::Create(
TransactionId => $args{‘TransactionId’},
Parent => $args{‘Parent’},
ContentType => $Attachment->mime_type,
Headers => $head,
MessageId => $MessageId,
Subject => $Subject,
);

    unless ($id) {
        $RT::Logger->crit("Attachment insert failed - ".

$RT::Handle->dbh->errstr);
}

    foreach my $part ( $Attachment->parts ) {
        my $SubAttachment = new RT::Attachment( $self->CurrentUser );
        my ($id) = $SubAttachment->Create(
            TransactionId => $args{'TransactionId'},
            Parent        => $id,
            Attachment    => $part,
        );
        unless ($id) {
            $RT::Logger->crit("Attachment insert failed: ".

$RT::Handle->dbh->errstr);
}
}
return ($id);
}

#If it's not multipart
else {

    my ($ContentEncoding, $Body) = $self->_EncodeLOB(
        $Attachment->bodyhandle->as_string,

If the first SUPER::Create is successfull, the $id value isn’t undef, but
within the foreach loop, if an error ocurred adding Subattachments the crit
message is printed because the inner $id is undef, but the returned value is
the outer $id that is not undef, so the Ticket is created despite the error
adding a subattachment. Adding a return($id) inside the foreach loop solves
the problem an RT knows that Ticket can not be completly created.

This post is too long and don’t want to add more info (specially with this
terrible bad english), but despite the error returned to rt-mailgate when
Ticket creation fails, it tells fetchmail that everything is ok and email is
deleted. I’ve made an ugly hack to make it work, but I think that
check_for_failure() in rt-mailgate could get te correct return code, I’m not
a perl expert and couldn’t make it work, any help?

Anyway, do you think that this is a bug or a feature?
Best regards.
Andres.

rtlog.txt (11.3 KB)

Hello Andres,

As I understand the following change will fix the issue for you. If it
does then drop me a note and I’ll push it into core. If it doesn’t
then we should investigate more. Don’t forget to restart the web
server after patching.

I think it’s a bug. We can not guaranty that everything will work
perfectly when you’re out of space on disks, but this patch should
bring more sanity.

diff --git a/lib/RT/Attachment_Overlay.pm b/lib/RT/Attachment_Overlay.pm
index e3c1b9c…8c60185 100644
— a/lib/RT/Attachment_Overlay.pm
+++ b/lib/RT/Attachment_Overlay.pm
@@ -154,6 +154,7 @@ sub Create {

     unless ($id) {
         $RT::Logger->crit("Attachment insert failed - ".

$RT::Handle->dbh->errstr);

  •        return ($id);
       }
    
       foreach my $part ( $Attachment->parts ) {
    

@@ -165,6 +166,7 @@ sub Create {
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed: ".
$RT::Handle->dbh->errstr);

  •            return ($id);
           }
       }
       return ($id);On Fri, Jul 9, 2010 at 1:55 PM, Andrés Schiavo <andresschiavo@gmail.com> wrote:
    

Hi, I’m currently working with a RT 3 instance and I’ve found that some
Tickets could be created with missing content under specific situations.
This is my scenario:

  • RT 3.8.7 runnig on RHEL5 with perl 5.8.8
  • Oracle 10g database
  • External mail server and fetchmail to recover emails
    This RT instance is quite special, we recive a lot of spam (we are working
    to fix it) and the database grows quickly. During working days our
    monitoring agents alert us about reaching database space limit, but if this
    happen on weekend, nobody extends de DB until Monday.
    Because of Spam we have configured fetchmail with “no keep” option, so if
    Ticket creation fails and fetchmail does not recieve an error return code
    the information of the email is lost.
    I know that this are a lot of “special situations” but I think that
    rt-mailgate should return non zero result when RT couldn’t create the Ticket
    correctly.
    I haven’t try to reproduce with other databases than Oracle, but I’ve
    reproduce this behavior on two different Oracle instances
    This are the steps to reproduce the issue:
    When rt database tablesapce is full, fetchmail try to recover an email (with
    an attachment or an html email).
    Ticket is created but we end up with no attach or no text if email was html.
    Fetchmail recive a 0 ret code and erase email from server.
    I’ve attach the rt log when attachment insert fails.
    I don’t know if this is a bug or that’s the way it’s supposed to work, but
    we can’t loose the email information.
    If this is a bug, I think that could be generated by the scope of the
    variable $id in this code (Attachment_Overlay line 140)

    If a message has no bodyhandle, that means that it has subparts (or

appears to)
# and we should act accordingly.
unless ( defined $Attachment->bodyhandle ) {
my ($id) = $self->SUPER::Create(
TransactionId => $args{‘TransactionId’},
Parent => $args{‘Parent’},
ContentType => $Attachment->mime_type,
Headers => $head,
MessageId => $MessageId,
Subject => $Subject,
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed - ".
$RT::Handle->dbh->errstr);
}
foreach my $part ( $Attachment->parts ) {
my $SubAttachment = new RT::Attachment( $self->CurrentUser );
my ($id) = $SubAttachment->Create(
TransactionId => $args{‘TransactionId’},
Parent => $id,
Attachment => $part,
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed: ".
$RT::Handle->dbh->errstr);
}
}
return ($id);
}
#If it’s not multipart
else {
my ($ContentEncoding, $Body) = $self->_EncodeLOB(
$Attachment->bodyhandle->as_string,

If the first SUPER::Create is successfull, the $id value isn’t undef, but
within the foreach loop, if an error ocurred adding Subattachments the crit
message is printed because the inner $id is undef, but the returned value is
the outer $id that is not undef, so the Ticket is created despite the error
adding a subattachment. Adding a return($id) inside the foreach loop solves
the problem an RT knows that Ticket can not be completly created.
This post is too long and don’t want to add more info (specially with this
terrible bad english), but despite the error returned to rt-mailgate when
Ticket creation fails, it tells fetchmail that everything is ok and email is
deleted. I’ve made an ugly hack to make it work, but I think that
check_for_failure() in rt-mailgate could get te correct return code, I’m not
a perl expert and couldn’t make it work, any help?
Anyway, do you think that this is a bug or a feature?
Best regards.
Andres.

Best regards, Ruslan.

Hello Ruslan, thanks for response

this patch alone does not fix the issue.
The last post was too long and I’ve preferred to split my solution for the
issue into several messages.
I need to change this line in Transaction_Overlay.pm

— Transaction_Overlay.pm.orig 2010-07-09 14:45:52.000000000 +0200
+++ Transaction_Overlay.pm 2010-07-09 14:46:32.000000000 +0200
@@ -513,11 +513,11 @@
my $Attachment = RT::Attachment->new( $self->CurrentUser );
my ($id, $msg) = $Attachment->Create(
TransactionId => $self->Id,
Attachment => $MIMEObject
);

  • return ( $Attachment, $msg || $self->loc(“Attachment created”) );
  • return ( $id, $msg || $self->loc(“Attachment created”) );
    }

}}}

}}}

And finally this ugly patch to rt-mailgate, I hope someone with higher
skills in perl/mason could make something better with the returned status.

— rt-mailgate.orig 2010-07-09 14:57:49.000000000 +0200
+++ rt-mailgate 2010-07-09 15:18:27.000000000 +0200
@@ -61,6 +61,7 @@
$DYNAMIC_FILE_UPLOAD = 1;

use constant EX_TEMPFAIL => 75;
+use constant EX_UNKNOWERR => 76;
use constant BUFFER_SIZE => 8192;

my %opts;
@@ -131,7 +132,18 @@
my $content = $r->content;
print STDERR $content .“\n” if $opts{‘debug’};

-if ( $content !~ /^(ok|not ok)/ ) {
+if ( $content !~ /^(ok)/ ) {

  • Ticket could not be created for unknow reason.

  • Return non zero to avoid that fetchmail clear email from mail server.

  • print STDERR <<EOF;
    +RT server error.
    +The RT server sends an unexpected error.
    +EOF

  • exit EX_UNKNOWERR;
    +} elsif ( $content !~ /^(not ok)/ ) {

    It’s not the server’s fault if the mail is bogus. We just want to

know that
# something came out of the server.
@@ -145,10 +157,10 @@
EOF

 exit EX_TEMPFAIL;

+} else {

  • exit;
    }

-exit;
END {
unlink $message{‘filename’} if $message{‘filename’};
}

I hope those patches fix the issue and don’t break anything else
Andrés.2010/7/9 Ruslan Zakirov ruz@bestpractical.com

Hello Andres,

As I understand the following change will fix the issue for you. If it
does then drop me a note and I’ll push it into core. If it doesn’t
then we should investigate more. Don’t forget to restart the web
server after patching.

I think it’s a bug. We can not guaranty that everything will work
perfectly when you’re out of space on disks, but this patch should
bring more sanity.

diff --git a/lib/RT/Attachment_Overlay.pm b/lib/RT/Attachment_Overlay.pm
index e3c1b9c…8c60185 100644
— a/lib/RT/Attachment_Overlay.pm
+++ b/lib/RT/Attachment_Overlay.pm
@@ -154,6 +154,7 @@ sub Create {

    unless ($id) {
        $RT::Logger->crit("Attachment insert failed - ".

$RT::Handle->dbh->errstr);

  •        return ($id);
      }
    
       foreach my $part ( $Attachment->parts ) {
    

@@ -165,6 +166,7 @@ sub Create {
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed: ".
$RT::Handle->dbh->errstr);

  •            return ($id);
          }
      }
       return ($id);
    

On Fri, Jul 9, 2010 at 1:55 PM, Andrés Schiavo andresschiavo@gmail.com wrote:

Hi, I’m currently working with a RT 3 instance and I’ve found that some
Tickets could be created with missing content under specific situations.
This is my scenario:

  • RT 3.8.7 runnig on RHEL5 with perl 5.8.8
  • Oracle 10g database
  • External mail server and fetchmail to recover emails
    This RT instance is quite special, we recive a lot of spam (we are
    working
    to fix it) and the database grows quickly. During working days our
    monitoring agents alert us about reaching database space limit, but if
    this
    happen on weekend, nobody extends de DB until Monday.
    Because of Spam we have configured fetchmail with “no keep” option, so if
    Ticket creation fails and fetchmail does not recieve an error return code
    the information of the email is lost.
    I know that this are a lot of “special situations” but I think that
    rt-mailgate should return non zero result when RT couldn’t create the
    Ticket
    correctly.
    I haven’t try to reproduce with other databases than Oracle, but I’ve
    reproduce this behavior on two different Oracle instances
    This are the steps to reproduce the issue:
    When rt database tablesapce is full, fetchmail try to recover an email
    (with
    an attachment or an html email).
    Ticket is created but we end up with no attach or no text if email was
    html.
    Fetchmail recive a 0 ret code and erase email from server.
    I’ve attach the rt log when attachment insert fails.
    I don’t know if this is a bug or that’s the way it’s supposed to work,
    but
    we can’t loose the email information.
    If this is a bug, I think that could be generated by the scope of the
    variable $id in this code (Attachment_Overlay line 140)

    If a message has no bodyhandle, that means that it has subparts (or

appears to)
# and we should act accordingly.
unless ( defined $Attachment->bodyhandle ) {
my ($id) = $self->SUPER::Create(
TransactionId => $args{‘TransactionId’},
Parent => $args{‘Parent’},
ContentType => $Attachment->mime_type,
Headers => $head,
MessageId => $MessageId,
Subject => $Subject,
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed - ".
$RT::Handle->dbh->errstr);
}
foreach my $part ( $Attachment->parts ) {
my $SubAttachment = new RT::Attachment( $self->CurrentUser );
my ($id) = $SubAttachment->Create(
TransactionId => $args{‘TransactionId’},
Parent => $id,
Attachment => $part,
);
unless ($id) {
$RT::Logger->crit("Attachment insert failed: ".
$RT::Handle->dbh->errstr);
}
}
return ($id);
}
#If it’s not multipart
else {
my ($ContentEncoding, $Body) = $self->_EncodeLOB(
$Attachment->bodyhandle->as_string,

If the first SUPER::Create is successfull, the $id value isn’t undef, but
within the foreach loop, if an error ocurred adding Subattachments the
crit
message is printed because the inner $id is undef, but the returned value
is
the outer $id that is not undef, so the Ticket is created despite the
error
adding a subattachment. Adding a return($id) inside the foreach loop
solves
the problem an RT knows that Ticket can not be completly created.
This post is too long and don’t want to add more info (specially with
this
terrible bad english), but despite the error returned to rt-mailgate when
Ticket creation fails, it tells fetchmail that everything is ok and email
is
deleted. I’ve made an ugly hack to make it work, but I think that
check_for_failure() in rt-mailgate could get te correct return code, I’m
not
a perl expert and couldn’t make it work, any help?
Anyway, do you think that this is a bug or a feature?
Best regards.
Andres.


Best regards, Ruslan.

I’m sorry, the last patch for rt-mailgate was wrong…this one works fine.
Best regards.
Andres.

— rt-mailgate.orig 2010-07-12 11:13:10.000000000 +0200
+++ rt-mailgate 2010-07-12 21:54:14.000000000 +0200
@@ -61,6 +61,7 @@
$DYNAMIC_FILE_UPLOAD = 1;

use constant EX_TEMPFAIL => 75;
+use constant EX_UNKNOWERR => 76;
use constant BUFFER_SIZE => 8192;

my %opts;
@@ -131,7 +132,9 @@
my $content = $r->content;
print STDERR $content ."\n" if $opts{‘debug’};

-if ( $content !~ /^(ok|not ok)/ ) {
+if ( $content =~ /^(ok)/ ) {

  • exit;
    +} elsif ( $content =~ /^(not ok)/ ) {

    It’s not the server’s fault if the mail is bogus. We just want to

know that
# something came out of the server.
@@ -145,9 +148,16 @@
EOF

 exit EX_TEMPFAIL;

-}
+} else {

  • print STDERR <<EOF;
    +RT server error.
    +The RT server sends an unexpected error.
    +EOF

-exit;

  • exit EX_UNKNOWERR;
    +}

END {
unlink $message{‘filename’} if $message{‘filename’};