Procmail alternative?

Phree

Member
Nov 17, 2005
20
0
151
South Coast of England
Hi,

I have been searching thru the forums before asking this, but I don't appear to be able to find the answer.

I have a feature on my site that allows people with mobile phones to send multimedia messages and their pictures then appear on the website. If you like, it's a daily, mobile blog. It is slowly starting to become quite popular, however some users don't have the ability to send a multimedia message. This could be because their phone doesn't support it, or their network operator doesn't allow them to send outside of the network. So the alternative is to email. I have seen other sites that have this ability...A user sends an email via their phone using [email protected] and then using some scripts, the server picks up the email and knows which account to send it to. The ones I have seen use procmail. I contacted my server hosts today to ask them if procmail is installed as I have been trying to do the same, but failing everytime. The response from my hosts was:

"Hello,

Unfortunately, we don't have Procmail installed on any servers and won't be installing it as it's often used for spam relaying. If there's any alternative software you want installing, please let us know and we'll look into it."

So I'm wondering if anyone could please point me in the direction of an alternative to procmail?

I would be very grateful for any help!

Neil.
 

Phree

Member
Nov 17, 2005
20
0
151
South Coast of England
chirpy,

I have been reading up about using an exim filter, but I'm not really sure how to go about doing what I need to do...I realise you guys offer the advice free of charge & I'm not asking for someone to give a full implementation plan for me(!) but if anyone can offer some advice, I would be eternally grateful.

To quote from the install instructions of the scripts I am using:

Adding email upload support:
1) Create a user called mmsemail on your system
2) Copy the .procmailrc file to the mmsemail user's home directory.
3) Copy the recmail.pl to the same home directory
4) Edit recmail.pl so that the variables password and msgstore fit
your system
5) Setup your email server to catch all unknown email addresses and
send it to the mmsemail user. Consult your email server's
documentation on how to do that.
The .procmailrc file contains:
Code:
LOGFILE=/tmp/recmail.log

:0
| /home/mmsemail/recmail.pl
And the recmail.pl file contains the scripting that breaks the email down into the parts it needs - such as Subject, image attachments & most importantly, the first part of the email address which contains their account name. It then proceeds to push the parts into the correct directories in order to be displayed on the website.

Phew! So that's what I need to do...But I'm just not sure how to actually do it. Following the link you posted earlier, am I right to say I have to completely ignore the first link because I cannot use anything that relates to procmail? -

1. Use a Forwarder pipe | to send the email through the procmail binary
http://www.exim.org/exim-html-4.40/...Q_5.html#TOC186

2. Use Exim's equivalent of filters:
http://www.exim.org/exim-html-4.40/...filter_toc.html
So if anyone can point me to the actual route I should follow, Mr :confused: will turn into Mr :D ! Up until this afternoon, I had never even heard of exim :eek:

EDIT: Having read a bit more on filters, would this work in my .forward:
Code:
#   Exim filter
pipe "$home/mmsemail/recmail.pl
Unfortunately, I can't try this right now as I'm stuck at work on the dreaded night shift :mad:
 
Last edited:

chirpy

Well-Known Member
Verifed Vendor
Jun 15, 2002
13,437
33
473
Go on, have a guess
What you probably want to do is more simple. Create a Forwarder in cPanel for the email address you want to use and set the following as where the address is forwarded to:

|/home/mmsemail/recmail.pl

That first character is the pipe character.
 

Phree

Member
Nov 17, 2005
20
0
151
South Coast of England
Hi chirpy,

many thanks for your post once again...It'll be no surprise to you that it worked!

However (there's always a however!). Part of my recmail program calls in a file called 'munpack' - this is supposed to strip incoming emails down to their seperate parts - subject/body/attachments. I do have a copy of it, but I don't think it works correctly. All the versions of it I have found on the net are uncompiled ones - and I don't know how I would go about compiling it. I only have access to my server thru CPanel and have no way I can run commands against files that I know of...Can anyone suggest how I would go about it?

Basically, I need to use the 'makefile' command I think...
 

chirpy

Well-Known Member
Verifed Vendor
Jun 15, 2002
13,437
33
473
Go on, have a guess
You'll probably need the co-operation of your hosting provider to get something like munpack installed as it does need to be compiled from a shell session. This is easily done with:
wget ftp://ftp.andrew.cmu.edu/pub/mpack/mpack-1.6.tar.gz
tar -xzf mpack-1.6.tar.gz
cd mpack-1.6
./configure
make
This will generate the munpack binary which would then need to be moved into your account somewhere and referenced from your script.
 

Phree

Member
Nov 17, 2005
20
0
151
South Coast of England
Back again!

Thanks largely to your help, I now have the email facility to my site partly working. I can email from a pc to my web, include an attach pic and it all works great. However, when I send an email from a mobile, it doesn't work. All that is displayed on my site is the subject line. Looking at my error log, I get this: "Did not find anything to unpack from standard input".

When I compare the email from my mobile to an email from my pc, there is a fair difference in the headers...On the mobile email, I get this:

Content-Type: multipart/mixed; boundary="EPOC32-7,W_Nw5T,BqKlHJ+tzXmcLbT'b+NRSPpq+SfT8fmSTm+r,LL"

and on an email from a friend's phone (which also didn't work) it said:
Content-Type: TEXT/PLAIN; charset="UTF-8"
Content-Transfer-Encoding: Base64.

Whether it's something to do with the encoding or not, I don't know...But I'm hoping someone here might have an idea. Is there some kind of conversion I can them thru so they appear correctly?

Thanks for any help!
 

Phree

Member
Nov 17, 2005
20
0
151
South Coast of England
Ok, so I think I may have found something that could help me out...

"If you are having problems decoding a MIME message on such a system, you
need to convert the mail back into the standard format by removing the
system's nonstandard headers and moving the standard Internet headers
to the top of the message (separated from the message body with a
blank line)."

So...Does anyone know how I could actually do this? I guess it might be woirth posting up the script I am currently using and maybe someone could say "add this line here"; "delete that line there" etc...? Anyway, here it is:

Code:
#!/usr/bin/perl

use DBI;

$driver ="mysql";
$user = "myuser";
$password = "mypwd";
$munpack = "/path/to/munpack";
$msgstore = "/path/to/msgstore";
$reldir = "msgstore";

umask( 0 );

while ( $line = <STDIN> )
{
    @tmp = split( ": ", $line );

    if ( lc($tmp[0]) eq "to" )
    {
	chop( $tmp[1] );
	$to = $tmp[1];
    }
    elsif ( lc($tmp[0]) eq 'from' )
    {
	chop( $tmp[1] );
	$from = $tmp[1];
    }
    elsif ( lc($tmp[0]) eq 'subject' )
    {
	chop( $tmp[1] );
	$subject = $tmp[1];
    }
    elsif ( lc($tmp[0]) eq 'content-type' )
    {
	last;
    }
}

$dsn = "DBI:$driver:database=mydbase;host=localhost";
$dbh = DBI->connect( $dsn, $user, $password );
    
$id = isValid( $to, $from ) || die( "Not a valid user $to $from" );


$dirname = $msgstore . "/" . $$ . "_email";
mkdir( $dirname, 0775 );

open(UNPACK,"| $munpack -C $dirname > $dirname/info.txt 2> /dev/null" ) 
    || die( "Could not start unpacker program");

print( UNPACK $line );

while ( $line = <STDIN> )
{
    print( UNPACK $line );
}

close( UNPACK );

$info = $dirname . '/info.txt';

open( INFO, $info ) || die( "Could not open info file [$!]" );

$size = 0;
while ( $line = <INFO> )
{
    @tmp = split( " ", $line );
    $tmp[1] = substr( $tmp[1], 1, length($tmp[1])-2 );
    $content{$tmp[0]} = $tmp[1];

    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
     $atime,$mtime,$ctime,$blksize,$blocks)
	= stat( $dirname . "/" . $tmp[0] );
    $size += $blksize * $blocks;
    $content_size{$tmp[0]} = $size;
}

close( INFO );

$mid = storeMessage( $to, $id, $subject, int( $size / 1024 ) );

foreach $file ( keys(%content) ) 
{
    storeContent( $mid, $file, $content{$file}, $content_size{$file} );
}

$txt = getTextForMid( $mid );
if ( strlen( $txt ) > 0 )
{
    setTextForMid( $mid, $txt );
}


$dbh->disconnect();

sub storeContent
{
    ($mid, $file, $type, $size) = @_;
    $fname = $reldir  . "/" . $$ . "_email/". $file;
    $query = "INSERT INTO content VALUES " . 
	"(NULL, $mid, '$type', '$fname', $size )";
    chmod( 0775, $msgstore . "/" . $$ . "_email/". $fname );
    $sth = $dbh->prepare($query) || die;
    $sth->execute();
}

sub setTextForMid
{
    ( $mid, $txt ) = @_;
    $query = "UPDATE messages SET textmsg='$txt' WHERE id=$mid";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();
}

sub getTextForMid
{
    ($mid) = @_;

    $query = "SELECT fname FROM content WHERE mid=$mid && ".
	"contenttype='text/plain'";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();
    
    if ( @row = $sth->fetchrow() )
    {
	$fname = $row[0];
	open( TXTFILE, $msgstore . "../" . $fname );
	@content = <TXTFILE>;
	$txt = join('', @content);
	return $txt;
    }
    return "";
}

sub storeMessage
{
    ($to, $sid, $subject, $size ) = @_;
    $subject = $dbh->quote($subject);
    $query = "INSERT INTO messages VALUES " . 
	"(NULL, $sid, 1, '$to', $subject, NOW(), 'email', '0.0.0.0', 0, 0, '', 0  )";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();

    $query = "SELECT LAST_INSERT_ID() FROM messages";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();
    @row = $sth->fetchrow();
    $id = $row[0];

    $query = "UPDATE users SET nkbytes=nkbytes+$size, ".
	" lastupload=NOW(), ". 
	    " nuploads=nuploads+1 WHERE id=$sid";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();

    return $id;
}

#isValid
#to-address is on form p<number>@domain.com
#from-address is on form <MSISDN>@domain.com
sub isValid
{
    ($to, $from) = @_;
    @tos = split( "@", $to );
    $pwd = substr( $tos[0], 2 );
    if ( ($index = index( $pwd, "<" ) ) >= 0 )
    {
	$pwd = substr( $pwd, $index + 3 );
    }
    @froms = split( "@", $from );
    $msisdn = $froms[0];
    if ( ($index = index( $msisdn, "<" )) >= 0 )
    {
	$msisdn = substr( $msisdn, $index + 1 );
    }

    $query = "SELECT id FROM users WHERE msisdn='$msisdn' && phonepwd='$pwd'";
    $sth = $dbh->prepare($query) || die;
    $sth->execute();

    $id = 0;    
    if ( @row = $sth->fetchrow() )
    {
	$id = $row[0];
    }
    $sth->finish();

    $id || die( "msisdn is $msisdn and pwd is $pwd" );

    return $id;
}
Cheers all!