A practical example

In this example we are going to use the PHP library since it is a popular choice for integration with web frameworks.

The full code used in this example can be found here.

The PHP library of the API class can be found here.

Often email notifications of new posts are handled by the framework or community software already, and you would extend that functionally through hooks or other means. However for this example we are going to use a rudimentary piecemeal notification script, for simplicity's sake.

We are going to be using swiftmailer for this tutorial, so you will need some SMTP server and account details.

First put your credentials from your profile in a configuration file and also email details e.g.

<?php
// replyPUSH credentials
$accountNo = 'd7870ac3';
$secretID  = '?F=?H"r|["kc.7]-N\EMiHUu7eho3XZs';
$secretKey = '^PyxxPe6d{j!bL^dFiFcC^oqhSNOm>HO';

// site details
$siteName = 'Insect Nuts';
$siteEmail = 'admin@insectnuts.com'; // your email

// SMTP details
$smtpHost = 'mail.insectnuts.com';
$smtpPort = '587';
$smtpUser = 'InsectNuts';
$smtpPass = 'xxxxxxxx';

// fake user (will most likely be retrieving a user from your user base) 
$name    = 'Creepers';
$email   = 'creepers@gmail.com'; // email you are sending to

Here is the script the sends the email:

<?php
// replyPUSH API class
require('./library/class.replypush.php');

// get your replyPUSH credentials ($accountNo, $secretID, $secretKey)
// plus stmp details and faked user
require('./config/config.php');

// swiftmailer
require('./library/swiftmailer/lib/swift_required.php');

// transport method
$transport = Swift_SmtpTransport::newInstance($smtpHost, $smtpPort)
  ->setUsername($smtpUser)
  ->setPassword($smtpPass);

// mailer instance
$mailer = Swift_Mailer::newInstance($transport);

// dummy post
$subject      = 'How many legs?';
$slug         = 'how-many-legs';
$category     = 'Arthropods';
$postContent  = 'Do centipedes have 100 legs or what?';
$fromUserID   = 86;
$fromUserName = 'Ignorant';
$recordID     = 125;
$type         = 'newdisc';

$message = <<<EOT
<p>{$fromUserName} started a new discussion, ‘{$subject}’ in {$category}:</p>
<blockquote>{$postContent}</blockquote>
<p>You can check it out <a href="http://insectnuts.com/forum/discussion/{$recordID}/{$slug}">here</a></p>
<p></p>
<p>Have a great day!</p>
EOT;


// subject prefix
$subjectPrefix = "[{$siteName}] {$fromUserName} started a new discussion:";

//message prefix
$messagePrefix = '<a name="rp-message"></a><a href="http://replypush.com#rp-message"><wbr></a>';

// message suffix
$messageSuffix = <<<EOT
<p><br><b>***** reply service *****</b><br><br></p>
<p><b>You can reply by the link provided, or reply directly to this email.</b></p>
<p><span>Please put your message directly ABOVE the quoted message you get when you click reply.</span></p>
<p>Thank You.</p>
EOT;

//just noise
$timeStamp = time();
$randomSalt = mt_rand();

// custom 40 byte custom data 
$data = sprintf(
    "%08x%08x%-8s%08x%08x",
    $fromUserID,
    $recordID,
    $type,
    $timeStamp,
    $randomSalt
);

// lets use sha1 for hmac hash algorithm
$hashMethod = 'sha1';

// replyPUSH API class instance
$replyPush = new ReplyPush(
    $accountNo,
    $secretID,
    $secretKey,
    $email,
    $data,
    $hashMethod
);

// get reference that is verified by the service
// and will be used later for the reply notifications
$messageID = $replyPush->reference($withBrakets = FALSE);

// message 
$message = Swift_Message::newInstance()
    ->setTo(array($email=>$name))
    ->setSubject("{$subjectPrefix} {$subject}")
    ->setFrom(array($siteEmail => $siteName))
    ->setReplyTo(array(
        'post@replypush.net' => 'Ignorant [at] insectnuts.com'
    )) 
    ->setContentType('text/html') //HTML recommended
    ->setCharset('utf-8')
    ->setEncoder(Swift_Encoding::getQpEncoding())
    ->setBody("{$messagePrefix}{$message}{$messageSuffix}")
    ->setId($messageID);

$failures = array();

// send message
$sent = $mailer->send($message,$failures);

if(!$sent){
    echo "Email was not sent, the following failures occured: \n";
    foreach($failures As $failure)
        echo "  - {$failure}\n";
}else{
    echo "Email was sent succesfully!";
}

So when the recipient replies to the message, the Message-ID will be added to the References and In-Reply-To as per normal email client behaviour. It is sent to post@replypush.com and verified by the service, then sent on to the Notification URL.

The notification script will need to re-verify using the hashCheck() method.

You need to make sure the notification script is publicly accessible and the url saved in your profile.

We will also be handling error notifications.

As we will be faking context again the comment will be dumped in ./log/comments.txt so make it writeable.

You need first a reference for long error messages:

<?php
// $errorMessages['NoEOM'] = 'You need to end your reply with /eom on a new line.';
$errorMessages['NoMsg'] = 'We could not find a message in your reply.';
$errorMessages['NoMark'] = 'We could not process your reply, please reply above the quoted message.';

Here is the script that receives and processes the incoming notifications:

<?php
// replyPUSH API class
require('./library/class.replypush.php');

// get your replyPUSH credentials ($accountNo, $secretID, $secretKey)
// plus stmp details and faked user
require('./config/config.php');

// swiftmailer
require('./library/swiftmailer/lib/swift_required.php');

// transport method
$transport = Swift_SmtpTransport::newInstance($smtpHost, $smtpPort)
  ->setUsername($smtpUser)
  ->setPassword($smtpPass);

// mailer instance
$mailer = Swift_Mailer::newInstance($transport);


// get an array of error messages
require('./locale/errormessages.php');

/**
 * @@ denied @@
 * 
 * Deny invalid notifications
 * 
 * @return void
 */
function denied(){
    header("HTTP/1.0 403 Denied");
    exit();
}

/**
 * @@ processError @@
 * 
 * Get long error message and send error email
 * 
 * @param string $error the short hand error message
 * @param object $user 
 * @param string $references
 * @param string $subject
 * 
 * @return void
 */

function processError($error, $email, $name, $subject){
    $hasErrorMessage = array_key_exists($error, $errorMessages);
    if($hasErrorMessage)
        sendError($email, $name, $errorMessages[$error], $subject);
}

/**
 * @@ sendError @@
 * 
 * Send error email
 * 
 * @param string $email
 * @param string $name
 * @param string $errorMessage
 * @param string $subject
 * 
 * @return void
 */

function sendError($email, $name, $errorMessage, $subject){

    $errorPrefix =  <<<EOT
An error has occurred:

EOT;
    $errorSuffix = <<<EOT

Reply to the original message not this one

Thank you
EOT;

    // message 
    $message = Swift_Message::newInstance()
        ->setTo(array($email=>$name))
        ->setSubject("{$subjectPrefix} {$subject}")
        ->setFrom(array($siteEmail => $siteName))
        ->setContentType('text/plain')
        ->setCharset('utf-8')
        ->setBody("{$errorPrefix}{$errorMessage}{$errorSuffix}");

    // send message
    $result = $mailer->send($message);

}

/**
 * @@ saveReply @@
 * 
 * Save comment to log
 * 
 * @param string $email
 * @param string $name
 * @param array[string]string|array $notification
 * 
 * @return void
 */

function saveReply($email, $name, $content, $subject){
   if(isset($content['text/html'])){
       $content = $content['text/html'];
   }else if(isset($content['text/plain'])){
       $content = $content['text/plain'];
   }
   $comment = <<<EOT
Comment by {$name} <{$email}> in reply to "$subject":
{$content}
----------------------------------------------------

EOT;
   file_put_contents('./log/comments.txt', $comment , FILE_APPEND);
}

/*
* PROCESSING BEGINS
*/

$notification = $_POST;
// need postback
if(empty($notification)) return;

// need msg_id and in_reply_to
if(!isset($notification['msg_id']) || 
   !isset($notification['in_reply_to'])) return;

// DO THIS HERE: check that  msg_id is not already stored in your database

// check user exists if not deny
if($notification['from'] != $email )
   denied();


// use API class to check reference
// in_reply_to is original message Message-ID
// will detect hash method from reference
$replyPush = new ReplyPush(
    $accountNo,
    $secretID,
    $secretKey,
    $email,
    $notification['in_reply_to'] // can include reference in place of data
);

if($replyPush->hashCheck()){
    //split 56 bytes into 8 byte components and process
    $messageData = str_split($replyPush->referenceData,8);
    $fromUserID = hexdec($messageData[2]);
    $recordID = hexdec($messageData[3]);
    $type = trim($messageData[4]);

    // error handling
    if(isset($notification['error'])){
        processError(
            $email,
            $name,
            $notification['error'],
            $notification['subject']
        );
        return;
    }

    // check context type
    if($type == 'newdisc'){

        // DO THIS HERE: you want to check that is a valid discussion
        // with the $fromUserID (original poster) and $recordID
        // and the user replying is allowed to do so.

        // REMEMBER: you can send community specific errors via sendError()

        // REMEMBER: input and output sanitation and processing 
        // is your responsibility.  
        // The service does nothing to cleanse but try to strip out 
        // parts of the email which aren't part of the reply. 

       // save reply in context
       if(isset($notification['content']))
           saveReply(
               $name, 
               $email, 
               $notification['content'],
               $notification['subject']
           );
    }
}else{
   denied();
}

// DO THIS HERE:  store msg_id and $notification (serialized)
// for simple reference
// probably want to unset($notification['content']) first

Your directory structure should look something like this:

 - notify.php
 - send.php
 - config
   - config.php
 - library
   - class.replypush.php
   - swiftmailer
 - locale
   - errormessages.php
 - log
   - comments.txt

You can run send.php from the command line php send.php or if it is served by the web server, then point to it a browser. You should receive the email to the supplied address.

Assuming you have already saved the publicly acceptable Notification URL pointing to notify.php in your profile, then you may reply as per the email instructions. If successful, the reply should be saved to .log/comments.txt.

To create a simple web interface for viewing the incoming messages you could use the following html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>replyPUSH - Reply By Email Example</title>
  <meta name="description" content="Reply By Email Example">
  <meta name="author" content="replyPUSH.com">
  <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
  <script>
    jQuery(document).ready(function($){
        var interval = 1000;
        var poll = setInterval(function(){
            $('#msg-container').load(
                'log/comments.txt?'+(new Date().getTime()),
                function(response, status, xhr){
                    if (status == "error"){
                        $(this).val("ERROR: " + xhr.status + " " + xhr.statusText );
                    }

                    $(this).scrollTop($(this)[0].scrollHeight);
                }
            );
        },interval);
    });
  </script>
  <style>
    #msg-container{
        width:99%;
        height:400px;
        overflow:hidden
    }
  </style>
</head>

<body>
  <h1>Reply By Email Demo</h1>
  <p>Replies should appear bellow:</p>
  <textarea id="msg-container"></textarea>
</body>
</html>