SMF incoming email capability

Introduction

Although this post can be found on DevTome my feeling was that having a second copy stored here on HIVE's blockchain had a pleasant decentralized vibe to it. This entry is still a work in progress with more code to yet to be added.

Background

This article is to explain how to install incoming email capability into the SimplyMachines forum on a Linux server. It was done as a software bounty for the DevCoin development team.

Project SMFemail

The completed package file contains the following files:

README_SMFEmail.txt
catcher_conf.php
catcher.php
challenge_response.php
parseMail.php

The package file is named SMFemail-1.4.tar. It is offline as of this writting during server movement of trollkeep.com.

Place the package, SMFemail-1.4.tar, in the root directory of the SMF installation. Extract it's contents with the Linux terminal command:

tar -xpvf SMFemail-1.4.tar

Using a text editor load catcher_conf.php and enter the proper information for your system setup in the DB access info and Misc. info areas of that file.

The script catcher.php requires a table in the database to store the incoming emails until the user completes a challenge response which will be sent to them via email. It should be created in the same database and prefix which you configured in the catcher_conf.php file. With my choice of prefix it was named smf_email_queue.

Use the CREATE command to create the table in your database like MySQL. ie:

CREATE TABLE smf_email_queue (
frommemberid mediumint(8) unsigned,
froma varchar(255),
subject varchar(255),
message text,
memberid mediumint(8) unsigned,
tmp_id_pm_head int(10) unsigned,
time_stamp int(12) unsigned
);

You will want to create an account on your SM Forum which will be the dummy sender of emails from senders who are not presently registered on the forum. My suggestion is to use Mailman. Incoming emails that cannot find a member name to match that of the email will use that account. You will be asked to enter the instance of that dummy account when configuring catcher_conf.php.

[Edit 02/14/15 : Not sure that MailMan is still required with Shattienator's Outgoing SMF Mail mod which is in pre-release as of this writting]

Once all those steps are completed the last order of business is to have any emails sent to the server, and having no registered account on that server, piped to the catcher.php script. Providing your server has a cpanel, then you can log into the cpanel and follow the Default Address link of the Mail category box. In the Advanced Options of the Default Address page Pipe to a program: should be chosen and then the path to catcher.php entered. For example, public_html/forum/catcher.php, if the forum directory is the root directory of your SMF installation. You will then have all emails that do not have a registered account on the server being piped to catcher.php.

If you do not have cpanel available, or choose not to use it, then you should explore how to pipe such emails using procmail's configuration.

Hopefully once finished all these steps you will have incoming email delivery set up for your SimpleMachines forum. There is also an outgoing email SMF Mod under development. When it is available for release a link will be added to this page.

Contact address: novacadian AT gmail.com

Code

FILE : README_SMFEmail.txt

The setup details for SMFEmail_1.2.tar can be found at:
http://www.devtome.com/doku.php?id=smf_incoming_email_capability
Novacadian - Feb 19, 2014

The needed scripts can be found in the SMFemail-1.4.tar package at:

http://trollkeep.com/SMFemail-1.4.tar

[Edit 02/27/24 : The package is currently offline during the server move of trollkeep.com]

The package includes:

README_SMFEmail.txt
catcher_conf.php
catcher.php
challenge_response.php
parseMail.php

Place the package, SMFemail-1.4.tar, in the root directory of the SMF installation. Extract it's contents with the command:

tar -xpvf SMFemail-1.4.tar

Using a text editor load catcher_conf.php and enter the proper information for your system setup in the DB access info and Misc. info areas of that file.

The script catcher.php requires a table in the database to store the incoming emails until the user completes a challenge response which will be sent to them via email. It should be created in the same database and prefix which you configured in the catcher_conf.php file. With my choice of prefix it was named smf_email_queue.

Use the CREATE command to create the table. ie:

CREATE TABLE smf_email_queue (
frommemberid mediumint(8) unsigned,
froma varchar(255),
subject varchar(255),
message text,
memberid mediumint(8) unsigned,
tmp_id_pm_head int(10) unsigned,
time_stamp int(12) unsigned
);

You will want to create an account on your SM Forum which will be the dummy sender of emails from senders who are not presently registered on the forum. My suggestion is to use Mailman. Incoming emails that cannot find a member name to match that of the email will use that account. You will be asked to enter the instance of that dummy account when configuring catcher_conf.php.

[Edit 02/14/15 : Not sure that MailMan is still required with Shattienator's Outgoing SMF Mail mod which is in pre-release ]

Once all those steps are completed the last order of business is to have any emails sent to the server, and having no registered account on that server, piped to the catcher.php script. Providing your server has a cpanel, then you can log into the cpanel and follow the Default Address link of the Mail category box. In the Advanced Options of the Default Address page Pipe to a program: should be chosen and then the path to catcher.php entered. For example, public_html/forum/catcher.php, if the forum directory is the root directory of your SMF installation. You will then have all emails that do not have a registered account on the server being piped to catcher.php.

If you do not have cpanel available, or choose not to use it, then you should explore how to pipe such emails using procmail's configuration.

Hopefully once finished all these steps you will have incoming email delivery set up for your SimpleMachines forum. There is also an outgoing email SMF Mod under development. When it is available for release a link will be added to this page.

Contact address: novacadian AT gmail.com

Code



README_SMFEmail.txt

The setup details for SMFEmail_1.2.tar can be found at:
http://www.devtome.com/doku.php?id=smf_incoming_email_capability
Novacadian - Feb 19, 2014

catcher_conf.php

<?php

// GNU GENERAL PUBLIC LICENSE
// Version 3, 29 June 2007

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see .

// novacadian - Feb. 17, 2014

//===============
// DB access info
//===============
// Replace below value with the access name for the Database eg. 'admin' $dbuser = 'username';
// Replace below value with the password for the Database eg. 'password'
$dbpass = 'password';
// Replace below value with the database name for the Database eg. 'smf_DB'
$dbname = 'database';
// Replace below value with the location the Database eg. 'localhost'
$dbhost = 'location';
// Table name prefix should be included below. With SMF this is most often smf_
$db_prefix="smf_";

//===============
// Misc. info
//===============

// Replace below value with the path to root directory of the SMF forum installation without a trailing backslash.
// eg. trollkeep.com/forum
$domainname="domainname.com/forum";
// Account to use if sender not a registered forum member..
$dummyaccount=0;
//Sender of the challenge response email
$replyemail="no-reply@domainname.com";
?>

catcher.php

#!/usr/bin/php -q
<?php

// GNU GENERAL PUBLIC LICENSE
// Version 3, 29 June 2007

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see .

// novacadian - Feb. 17, 2014

require("parseMail.php");
require("catcher_conf.php");

$members_table="$db_prefix"."members";
$email_queue_table="$db_prefix"."email_queue";
$personal_messages_table="$db_prefix"."personal_messages";
$email_white_table="$db_prefix"."email_white";
$pm_recipients_table="$db_prefix"."pm_recipients";
$MaxSizeInKB = 1024;

// Open STDIN
$fp = fopen("php://stdin", "r");
if (!$fp)
{
echo "Nothing in Standard In!";
fclose($fp);
exit();
}

// Take input from STDIN up to 1MB. This should be adjusted if a larger size is desired.
if ($MaxSizeInKB == -1)
{
while (!feof($fp))
{
$email .= fread($fp, 1024);
}
}
else
{
while (!feof($fp) && $i_limit < $MaxSizeInKB)
{
$email .= fread($fp, 1024);
$i_limit++;
}
}
// Close STDIN
fclose($fp);

$email_object=new parseMail($email);

$this_from=$email_object->from;
$this_to=$email_object->to;
$this_subject=$email_object->subject;
$this_received=$email_object->received;
$this_date=$email_object->date;
$this_message_id=$email_object->message_id;
$this_content_type=$email_object->content_type;
$this_part=$email_object->part;

$words = explode(" ", $this_from);
for ($x=0; $x < count($words); $x++)
{
$pos = strpos($words[$x], "@");
if ($pos == TRUE)
{
$tmp_words = str_replace ('>', '', str_replace('<', '', $words[$x]));
list($froma, $fromb) = explode('@', $tmp_words);
}
}

$to=$this_to;
$subject=$this_subject;
$message=$this_part[0]['content'];
//Clean all tags from message
$message=strip_tags($message);

//Below will get Member Name the email is addressed to so as to check against the SFM database.
$to = str_replace ('>', '', str_replace('<', '', $to));
$to = str_replace('"', '', $to);
list($toa, $tob) = explode('@', $to);

// Place the email address of sender at the bottom of the PM
$message.="\n\n===========================================================\nThis message was sent from: ".$tmp_words;

//Open the DB
$db = mysql_connect($dbhost,$dbuser,$dbpass) or die("Database error");
mysql_select_db($dbname, $db);

//Get the MemberID of the receiver of the email.
$query = sprintf("select id_member from $members_table where member_name='$toa'");
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$memberid=$row[0];

//Check for the MemberID of the sender of the email
$query = sprintf("select id_member from $members_table where member_name='$froma'");
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$frommemberid=$row[0];

//If no match is found have it sent from $dummyaccount.
if ($frommemberid == FALSE) {$frommemberid=$dummyaccount;}

//Get a random number to place into id_pm_head so that id_pm can be looked up.
$tmp_id_pm_head=rand(1,500000);

// Need to check here if email is on the member's white list. If it is then place it in the inbox
// with code below. Otherwise place it in the queue for the challenge response request. - Booner Feb14

$query = sprintf("select email_address from $email_white_table where id_member=$memberid AND email_address='$tmp_words'");
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$fromemail=$row[0];
if ($fromemail)
{

//Place info in smf_personal_messages
$query = sprintf("insert into $personal_messages_table (id_pm_head,id_member_from,from_name,subject,body) values ($tmp_id_pm_head,$frommemberid,'$froma','$subject','$message')");
$result = mysql_query($query);

// Look up id_pm using the random number as key
$query = sprintf("select id_pm from $personal_messages_table where id_pm_head=$tmp_id_pm_head");
$results = mysql_query($query);
$row = mysql_fetch_row($results);
$id_pm=$row[0];

//Change id_pm_head to match id_pm
$query = sprintf("update $personal_messages_table set id_pm_head=$id_pm where id_pm=$id_pm");
$result = mysql_query($query);

//Place info in smf_pm_recipients
$query = sprintf("insert into $pm_recipients_table (id_pm,id_member,is_new,is_read) values ($id_pm,$memberid,1,0)");
$result = mysql_query($query);

//Remove post from smf_email_queue
$query = sprintf("delete from $email_queue_table where memberid=$memberid and tmp_id_pm_head=$tmp_id_pm_head");
$result = mysql_query($query);

}
else
{
//Place info in smf_email_queue
$time_stamp=time();
$query = sprintf("insert into $email_queue_table (frommemberid,froma,subject,message,memberid,tmp_id_pm_head,time_stamp) values ($frommemberid,'$froma','$subject','$message',$memberid,$tmp_id_pm_head,$time_stamp)");
$result = mysql_query($query);

//Prepare and send a challenge response
$headers = 'From: xxxxxxxx' . "\r\n" .
'Reply-To: xxxxxxxx' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$subject="Challenge-response Request";
$message="Please click on the link below to complete the Challenge-response request to deliver your email to $this_to
\n\nhttp://xxxxxxxx/challenge_response.phpmemberid=$memberid&tmp_id_pm_head=$tmp_id_pm_head \n\nThank you.\n\n";
$message2=str_replace("xxxxxxxx", "$domainname", "$message");
$header2=str_replace("xxxxxxxx", "$replyemail", "$headers");

//Send challenge response email
mail($tmp_words, $subject, $message2, $header2);
}

//Close database
mysql_close($db);

// EOF

?>

challenge_response.php

#!/usr/bin/php -q
<?php

// GNU GENERAL PUBLIC LICENSE
// Version 3, 29 June 2007

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// novacadian - Feb. 17, 2014

require("catcher_conf.php");

$members_table="$db_prefix"."members";
$email_queue_table="$db_prefix"."email_queue";
$personal_messages_table="$db_prefix"."personal_messages";
$pm_recipients_table="$db_prefix"."pm_recipients";
//print_r($_GET);
$memberid=$_GET['memberid'];
$tmp_id_pm_head=$_GET['tmp_id_pm_head'];

//Open the DB
$db = mysql_connect($dbhost,$dbuser,$dbpass) or die("Database error");
mysql_select_db($dbname, $db);

// Look up id_pm using the random number as key
<$query = sprintf("select frommemberid,froma,subject,message from >$email_queue_table where memberid=$memberid and >tmp_id_pm_head=$tmp_id_pm_head");
$results = mysql_query($query);
$row = mysql_fetch_row($results);
$frommemberid=$row[0];
$froma=$row[1];
$subject=$row[2];
$message=$row[3];

echo $content;

//Place info in smf_personal_messages
$query = sprintf("insert into $personal_messages_table (id_pm_head,id_member_from,from_name,subject,body) values ($tmp_id_pm_head,$frommemberid,'$froma','$subject','$message')");
$result = mysql_query($query);

// Look up id_pm using the random number as key
$query = sprintf("select id_pm from $personal_messages_table where id_pm_head=$tmp_id_pm_head");
$results = mysql_query($query);
$row = mysql_fetch_row($results);
$id_pm=$row[0];

//Change id_pm_head to match id_pm
$query = sprintf("update $personal_messages_table set id_pm_head=$id_pm where id_pm=$id_pm");
$result = mysql_query($query);

//Place info in smf_pm_recipients
$query = sprintf("insert into $pm_recipients_table (id_pm,id_member,is_new,is_read) values ($id_pm,$memberid,1,0)");
$result = mysql_query($query);

//Remove post from smf_email_queue
$query = sprintf("delete from $email_queue_table where memberid=$memberid and tmp_id_pm_head=$tmp_id_pm_head");
$result = mysql_query($query);

//Close database
mysql_close($db);

$content="Thank you for completing the challenge response.
Your email will now be delivered. ";
echo $content;

// EOF

?>

parseMail.php

http://trollkeep.com/parseMail.html

[ Edit: 02/27/24 : parseMail.html is temporarily offline during server migration of trollkeep.com ]


KRno3osS_400x400.jpg

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center