0

I have the following scenerio:

SMTP server on the GNU/Linux machine is accepting mails. Accepted mail is being sent to procmail for further processing. Here's my .procmailrc:

VERBOSE=yes
LOGFILE=$HOME/procmail.log
SUBJECT=`formail -xSubject: | tr -d '\n' | sed -e 's/^ //' | /usr/bin/perl -MEncode -ne 'print encode ("utf8",decode ("MIME-Header",$_ )) '`
FROM=`formail -rt -xTo:`
DATE=`formail -xDate:`
BODY=`formail -I ""`
:0fbW
* ^From.*some_special_name@special_server.com
| echo "FROM:$FROM" > $HOME/res.txt; \
  echo "DATE:$DATE" >> $HOME/res.txt; \
  echo "SUB:$SUBJECT" >> $HOME/res.txt; \
  echo "BODY:" >> $HOME/res.txt; \
  echo $BODY >> $HOME/res.txt; process.py

This little script first creates a local file $HOME/res.txt and then launches another script called process.py. Now, the $HOME/res.txt is populated with the following entries:

FROM:some_special_name@special_server.com
DATE:Mon, 06 Oct 2014 13:14:32 +0200
SUB:Some subject
BODY:
This is a multi-part message in MIME format. --------------030006020609010705060803 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hello, Some kind of long tekst where I cannot see the line feed chars nor any other control chars...

The body contains the raw string without the original format of the body. What I mean by this is that \n or \t characters are filtered out. The process.py script demands the body part of the message to maintain the original format of the email message.

How can I achieve this?

Jaro
  • 1,232
  • 12
  • 12

1 Answers1

1

As always in shell scripts, you need to properly duoble-quote variables unless you specifically require the shell to perform token splitting and wildcard expansion on the value. See e.g. this answer for a detailed explanation.

  echo "$BODY" >>$HOME/res.txt; \

Additionally, I don't understand why you mix multiple actions like that. Between the lines, I guess you mean that process.py reads res.txt instead of its standard input; if it were reading standard input, it would receive the correct, unmangled message.

Without context, I'll go out on a limb and speculate that the f flag is also wrong. Unless process.py prints a new message on standard output which should replace the incoming message for the remainder of your Procmail recipe file, you should simply take it out.

There is also a race condition here: if multiple messages arrive at roughly the same time (where "same time" can be a rather wide window if your system is under heavy load), they will overwrite res.txt and trample over each others' results in unpredicable ways. The customary solution to that is to use a local lock file; but the vastly superior solution is to remove the need for a temporary file, and change process.py so that it reads standard input instead.

Since you are using Python anyway, I would do all the header parsing in Python, with the possible exception of formail -rtzxTo:, which is rather complex to reimplement; this would simplify your Procmail recipe significantly, and probably improve process.py (or the wrapper you create, if you cannot modify it).

Community
  • 1
  • 1
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks! This is exactly what I've been looking for. Frankly speaking I used to use the "" trick quite often while scripting, but this time my memory apparently failed me. By the way, I deleted the f flag, and all still works fine! – Jaro Oct 07 '14 at 10:08
  • Er, it's not a "trick", it's a fundamental feature of the shell. – tripleee Oct 07 '14 at 10:12
  • You're right! In answer to your query: yes, process.py reads res.txt for futher analysis. Good guess ;-) Quite likely I will need to elaborate it a bit more to send it to a remote server where the final version of process.py will take care of that file. Now it's in an early stage of development. – Jaro Oct 07 '14 at 10:18