For a couple of days, I've been trying to write procmail script.
I want to forward messages, and inject some text into message contents.
What I want to accomplish :
- someone send me e-mail, with word "weather" in the subject
- email is forwarded to address "mymail@somedomain.com"
- every forwarded email gets some added text in contents
But so far, no success.
In .procmail.log
, there's a message "procmail: Missing action"
SHELL=/bin/bash
VERBOSE=off
LOGFILE=/home/test/.procmail.log
LOGDATE_=`/bin/date +%Y-%m-%d`
:0
* ^Subject:.*weather
:0 bfw
| echo "This is injected text" ; echo "" ; cat
:0 c
! mymail@somedomain.com
When I looked into email source, I saw that text is injected.
But the place is wrong ...
Take a look:
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------148F3F0AD3D65DD3F3498ACA"
Content-Language: pl
Status:
X-EsetId: 37303A29AA1D9F60667466
This is injected text
This is a multi-part message in MIME format.
--------------148F3F0AD3D65DD3F3498ACA
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit
CONTENT CONTENT CONTENT
*********************************************************
Injected text should be placed, where content is. Now it is above ...
You don't explain your code, but it looks like that you are attempting to use multiple actions under a single condition. Use braces for that.
:0
* ^Subject:.*weather
{
:0 bfw
| echo "This is injected text" ; echo "" ; cat
:0 c
! mymail@somedomain.com
}
Just to summarize, every recipe must have a header line (the :0
and possible flags) and an action. The conditions are optional, and there can be more than one. A block of further recipes is one form of action so that satisfies these requirements (the other action types are saving to a folder, piping to a command, or forwarding to an email address).
To inject text at the top of the first MIME body part of a multipart message, you need to do some MIME parsing. Procmail unfortunately has no explicit support for MIME, but if you know that the incoming message will always have a particular structure, you might get away with something fairly simple.
:0
* ^Subject:.*weather
{
:0fbw
* ^Mime-version: 1\.0
* ^Content-type: multipart/
| awk '/^Content-type: text\/plain;/&&!s {n=s=1} \
n&&/^$/{n=0; p=1} \
1; \
p{ print "This is injected text.\n"; p=0 }'
:0 c
! mymail@somedomain.com
}
The body (which contains all the MIME body parts, with their headers and everything) is passed to a simple Awk script, which finds the first empty line after (what we optimistically assume is) the first text/plain
MIME body part header, and injects the text there. (Awk is case-sensitive, so the regex text might need to be adapted or generalized, and I have assumed the whitespace in the input message is completely regular. For a production system, these simplifying assumptions are unrealistic.)
If you need full MIME support (for example, the input message may or may not be multipart, or contain nested multiparts), my recommendation would be to write the injection code in some modern script language with proper MIME support libraries; Python would be my pick, though it is still (even after the email
library update in 3.6) is slightly cumbersome and clumsy.