Edit mail content before Notification

Hi,

I’m trying to edit the email content upon ticket creation or correspondence by using a custom script. The corresponding custom scrip with custom action runs before the notification scrip using a pre-built notification action.

Just as an illustrative example, I want to substitute first occurence of string “XXX” by string “YYY” in the body of the incoming email support request.

I have the two following scrips:

Scrip #1: Edit Email Content:

Action:


my $content = $self->TransactionObj->Content;

if ($content =~ m/XXX/) {
$content =~ s/XXX/YYY/si;
$self->TransactionObj->ContentObj->__Set( Field => ‘Content’, Value => $content);
}
return 1;


The issue is that the next scrip which sends a notification still uses the original content “XXX” rather than “YYY”.

What is the right method to call in order to change the initial body content of the incoming email so that the next Scrip wil use that modified content for notification? I’ve picked above code from the forum at Set Content via Scrip - #3 by Oriol_Soriano.

I’ve checked that the notification scrip is executed AFTER the edit scrip and that’s OK, and I also confirmed the substitution works by printing to STDERR…

Many thanks for your precious help,

Sam

I guess this may not be feasible as there is no reply? I’m trying to understand this issue and thought I would share my investigation in case it shed light to someone.

I checked which transactions and attachments are being logged upon making a new requstor correspondence and here is what sequentially happens with transactions and attachments in the database for the last correspondence test which includes string XXX in the email body:

  • SQL order used: select created,id,transactionid, subject,contenttype,contentencoding,content from attachments where transactionid IN (select id from transactions where objectid=56014 and objecttype=‘RT::Ticket’) order by created;
  • Results:
    |Created|id|transactionid|subject|contenttype|contentencoding|content|
    | — | — | — | — | — | — | — |
    |14/01/2019 14:48|3426343|1677793|Re: [Thermo NGS Support #56014] test RT|multipart/alternative|||
    |14/01/2019 14:48|3426345|1677793||text/html|none|<html>(…)
    <div>XXX</div>
    (…)</html>|
    |14/01/2019 14:48|3426344|1677793||text/plain|none|YYY|
    |14/01/2019 14:48|3426346|1677795|Re: [Thermo NGS Support #56014] test RT|text/plain|none|Requestor has replied to the following ticket:
    XXX|

So I can make multiple observations from above query results:

  1. the first 3 attachments have the same transactionid => test/plain attachment id = 1677793.
  2. the text/plain attachment id 3426344 does have the modified string where XXX became YYY (the Scrip worked here)
  3. the last attachment - notification sent to the owner - has a new transaction_id => 1677795 and String XXX is not replaced by YYY here - does this mean the content is read from memory rather than from the DB on that transaction?
  4. the text/html attachment still has XXX although I’m using both calls below in the scrips:
    $self->TransactionObj->ContentObj->__Set( Field => ‘Content’, Type => “text/html”, Value => $htmlContent);
    $self->TransactionObj->ContentObj->__Set( Field => ‘Content’, Type => “text/plain”, Value => $content);

Any pointers would be greatly appreciated… Many thanks!

A screenshot of the query results will ease understanding:

If this is just emailed in body contents that you need to change, you might be better off investigating whether your mail server can do some filtering before it hands it over to RT. That way the email is correct when the “On Create” scrips. The trouble I think you’re seeing is that you’re creating a new transaction after the creation transaction that modifies your body. RT will then process the scrips associated with that transaction (if any) before going back to running the rest of the scrips for the original transaction (which includes the body before you changed it).

If you want to edit the transaction content you can use a custom action for your scrip that sets the content of the transaction’s attachment. This example can get you started if this is the case:

return 0 unless $self->TransactionObj->HasContent;

my $content = $self->TransactionObj->ContentObj;
my ($ret, $msg) = $content->_Set( Field => 'Content', Value => 'test');
RT::Logger->error($msg) unless $ret;

return $ret;

Thanks for the suggestion, I have actually tried this in procmail in combiantion with fetchmail but the issue I get doing this is fetchmails later complains about that the message isn’t the expected length:
"fetchmail: message (…):1 was not the expected length (14039 actual != 43804 expected)

I didn’t find how to work around this and thought it would be easier with an RT Scrip.

Hi Craig and thanks for the suggestion.

This is more or less what I’m trying expect I was using 2 underscore characters instead of one (taht is __Set instead of _Set). I just tried with one underscore but the outcome is the same.

This is the custom action in my custom scrip:

return 0 unless $self->TransactionObj->HasContent;

my $content = $self->TransactionObj->Content(Type => “text/plain”);
my $contentObj = $self->TransactionObj->ContentObj;

if ($content =~ m/XXX/si) {
$content =~ s/XXX/YYY/si;
my ($ret, $msg) = $contentObj->_Set( Field => ‘Content’, Value => “$content”);
RT::Logger->error($msg) unless $ret;
}

return 1;

That scrip executes before the the next scrip which will send owner a notification - (default notification scrip).

This is what I can observe in the database:

The query I used to retrieved the last corresponding updates in tha attachment table:
select content from attachments where transactionid IN (select id from transactions where objectid=56014 and objecttype=‘RT::Ticket’) and transactionid >= 1677986 order by created, id;

So it looks like my email content modification Scrip does modify the correspondence logged as attachment, but the subsequenent notification Scrip (which I confirm is executed after the content modification Scrip) does not use that above saved attachment (id=3426537) and instead creates a new attachment (id=3426539). The thing I don’t understand is where does it retrieve the requestor reply content from? I’m inclined to say that it is from memory and that there is therefore no solution here, unless I use only one Scrip in which I send the notification after the content modification - if this is possible it could work, I would then just need to know to send a notification in the custom action code…

that is:

return 0 unless $self->TransactionObj->HasContent;

my $content = $self->TransactionObj->Content(Type => “text/plain”);
my $contentObj = $self->TransactionObj->ContentObj;

if ($content =~ m/XXX/si) {
$content =~ s/XXX/YYY/si;
my ($ret, $msg) = $contentObj->_Set( Field => ‘Content’, Value => “$content”);
RT::Logger->error($msg) unless $ret;
}

CODE to send a notification to Owner or AdminCCs as the default Scrip does

(…)

return 1;

Best regards,
Sam

Editing the email content is very necessary as the email content will be responsible for the reply we get. The given description in the post regarding that is very useful for us. Those who are having an issue regarding email or want to recover Gmail password can get back to us.

Unfortunately, I haven’t been able to successfully edit the email content using RT scrips.

It was so easy… I just needed to use templates instead of scrips.

I override the Autoreply template on the incoming general queue as below. The downside if I have to create several templates with the same code. A better option might be to overlay SendEmail.pm or edit the Transaction Content method?

(...)
{
   my $content = $Transaction->Content();
   if ($content =~ /This email originated from outside of the organization/si) {	$content =~ s/CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe\.//;
        $content =~ s/<div .*This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe\.<\/div>//si;
   }
   $content
}