How To Create Anonymous Email Addresses (Like Craigslist) Using Google Apps
by Jason -- July 22, 2010
In the following post, I’ll be explaining how to create anonymous email addresses for users of your website (similar to the one’s used on Craigslist) using Google Apps and a PHP script.
First off, I want to briefly explain why I wanted to create this tutorial. I recently created the anonymous email feature for candidates posting their profiles on KeysToChina.com (a new side-project). While doing so, I looked for tutorials on how to create the feature. Unfortunately, most of what I found was outdated and unnecessarily complicated. Hopefully, in the future, someone looking to implement a similar feature will be able to use this tutorial to create anonymous email addresses for their users.
High-Level Solution
The high-level solution to creating anonymous email addresses with Google Apps is to use the “catch-all” feature in Google Apps to send all email into a single inbox. Then, create a script to periodically check the address and forward on all emails based on who the email was sent to by looking into a database that links the anonymous email address with their real email address. (Whew!)
Catch-All Email Address in Google Apps
With each domain I own, I use Google Apps to manage email — it’s free and I highly recommend it. However, a feature that I was unaware of is a catch-all email address. With the catch-all email address, any email sent to your domain address that does not correspond with an existing user can either be automatically thrown away or placed into a user’s account.
To begin, set up an email account in Google Apps that will only be used for the catch-all anonymous user emails. Then in Google Apps, go to “Service Settings” > “Email”. Under catch-all address, enter the email account you’ve setup:
Important: Make sure to login to the catch-all account and enable IMAP (found in Settings), as you’ll need that enabled for the script below. It’s disabled by default.
Setting Up An Anonymous to Email Mapping Database
The database setup is a simple one-to-one setup. With each real email address, you’ll want to setup an anonymous email address that will be associated with that account. So, for example:
Anonymous email-address: [email protected]
Real email-address: [email protected]
Creating A Script to Check the Catch-All Email Address & Forward the Emails
Now that you’ve got an account setup to catch all of the anonymous emails and a database mapping the anonymous addresses with real email addresses, you’ll need to write a script to check the email address and forward the emails to the appropriate place. You can open the email account using IMAP:
{code type=php}
<?php
require_once(‘class.phpmailer.php’); //Used for simplicity
require_once ‘dbinfo.php'; //The database name, login, etc..
set_error_handler(“customError”); //I created a custom error
$login = ‘[email protected]';
$password = ‘HardToGuessPassword';
$server = ‘{imap.gmail.com:993/ssl/novalidate-cert}';
$connection = imap_open($server, $login, $password);
{/code}
Now that the email account is open, you’ll need to see if there are any new emails. If there are, you’ll want to see who the emails were sent to, match the recipient to their real address with your database mapping, and forward on the email:
{code type=php}
$mailboxinfo = imap_mailboxmsginfo($connection);
$messageCount = $mailboxinfo->Nmsgs; //Number of emails in the inbox
for ($MID = 1; $MID <= $messageCount; $MID++)
{
$EmailHeaders = imap_headerinfo($connection, $MID); //Save all of the header information
$Body = imap_qprint(imap_fetchbody($connection, $MID, 1)); //The body of the email to be forwarded
$MessageSentToAllArray = $EmailHeaders->to; //Grab the “TO” header
$MessageSentToAllObject = $MessageSentToAllArray[0];
$MessageSentToMailbox = $MessageSentToAllObject->mailbox; //Everything before the “@” of the sender
$MessageSentToHost = $MessageSentToAllObject->host; //Everything after the “@” of the sender
$MessageSentFromAllArray = $EmailHeaders->from; //Grab the “FROM” header
$MessageSentFromAllObject = $MessageSentFromAllArray[0];
$MessageSentFromMailbox = $MessageSentFromAllObject->mailbox; //Everything before the “@” of the sender
$MessageSentFromHost = $MessageSentFromAllObject->host; //Everything after the “@” of the sender
$MessageSentFromName = $MessageSentFromAllObject->personal; //The name of the person who sent the email
$toArray = searchRecipient($MessageSentToMailbox); //Find the correct person to send the email to
if ($toArray == FALSE) //If the alias they entered doesn’t exist…
{
$bounceback = “Sorry, your message sent to $MessageSentToMailbox@$MessageSentToHost does not appear to be correct.”
/* Send a bounceback email */
$mail = new PHPMailer(); // defaults to using php “mail()”
$mail -> ContentType = ‘text/plain'; //Plain email
$mail -> IsHTML(false); //No HTML
$the_body = wordWrap($bounceback, 70); //Word wrap to 70 characters for formatting
$from_email_address = “[email protected]”;
$mail->AddReplyTo($from_email_address, ‘KeysToChinaJobs.Com’);
$mail->SetFrom($from_email_address, ‘KeysToChinaJobs.Com’);
$address = “$MessageSentFromMailbox@$MessageSentFromHost”; //Who we’re sending the email to
$mail->AddAddress($address, $MessageSentFromName);
$mail->Subject = “Candidate Inquiry”; //Subject of the email
$mail->Body = $the_body;
if(!$mail->Send()) //If the mail fails, send to customError
{
customError(1, $mail->ErrorInfo, ‘keys-anon-email.php’, ‘sending the email’);
}
}
else //If the candidate address exists, forward on the email
{
$mail = new PHPMailer(); // defaults to using php “mail()”
$mail -> ContentType = ‘text/plain'; //Plain E-mail
$mail -> IsHTML(FALSE); //No HTML
$the_body = wordwrap($Body, 70); //Wordwrap for proper email formatting
$from_email_address = “$MessageSentFromMailbox@$MessageSentFromHost”;
$mail->AddReplyTo($from_email_address, $MessageSentFromName);
$mail->SetFrom($from_email_address, $MessageSentFromName);
$address = $toArray[1]; //Who we’re sending the email to
$mail->AddAddress($address, $toArray[0]); //The name of the person we’re sending to
$mail->Subject = $EmailHeaders->subject; //Subject of the email
$mail->Body = ($the_body);
if(!$mail->Send()) //If mail fails, go to the custom error
{
customError(1, $mail->ErrorInfo, ‘keys-anon-email.php’, ‘sending the email’);
}
}
/* Mark the email for deletion after processing */
imap_delete($connection, $MID);
}
imap_expunge($connection); // Expunge processes all of the emails marked to be deleted
imap_close($connection);
{/code}
With the comments in the code, hopefully the code is pretty straight-forward. I kept it very simple and sent only text emails. Also, to make it easier, I’ve used phpMailer. This can be downloaded here. The download includes great examples and helpful instructions to quickly get up and running.
Setting Up A Cron Job
A cron job can be used to automate your check email script. You can set up the script to be run every minute if you want, or only once-a-day. For this particular script, I went with every 5 minutes.
I use Bluehost for hosting, which uses cPanel. Cron Jobs are located in the “Advanced” section of cPanel. The command to run the script via a Cron job is going to vary by account and host, but here’s the command I used:
/usr/bin/php -q /homeX/username/path-to-script/file-name.php
Look on the home page of your cPanel to find out if there’s a number next to “home” and what your “username” is.
Check the Spam Folder!
After creating the script, doing some basic tests and getting things working, everything was going great. I decided to further test the script using my Hotmail and Yahoo! email addresses. From some reason, Yahoo! emails were never reaching the catch-all email account. I searched on Google, posted on the Google help forums, but I couldn’t figure out why only messages sent from Yahoo were never reaching the catch-all email address.
Finally, I figured out that Google was automatically placing these emails into the Spam folder. I didn’t notice this earlier, because Google automatically hides the Spam folder on new accounts. The lesson of the story is, if you’re noticing some emails aren’t showing up, check the Spam folder.
To solve this problem, I decided to create a second script to automatically check the Spam folder. This was easy and only required me to edit one line:
Change this:
{code type=php}
$server = ‘{imap.gmail.com:993/ssl/novalidate-cert}';
{/code}
To this:
{code type=php}
$server = ‘{imap.gmail.com:993/ssl/novalidate-cert}[Gmail]/Spam';
{/code}
Everything else is the same.
Big thanks to Ben from TechCofounder for helping me figure this out!
Be awesome and help us share:
it went over my head, but still very educational!
Great post.
Signing up w/Google Apps for my domains.
Thanks!
it was very interesting to read http://www.lifeaftercubes.com
I want to quote your post in my blog. It can?
And you et an account on Twitter?
Hi jason, great post! Thank you for this:
$server = ‘{imap.gmail.com:993/ssl/novalidate-cert}[Gmail]/Spam';
It really helped me a lot here in my project!!!
Again, big thanks!
Hi Ninjazhai,
Awesome, glad I could help!
Jason
Hi Jason,
bet you think this one is elementary but how can I find out the true identity of someone who is posting an anonymous e-mail at Craigslist? Also, if someone deletes their thumbnails from their browser do they leave a digital signature? How can I catch them for criminal activity if that is the case. Thanks for your help.
Hi Monica,
Thanks for the comment. The only two ways I can think of finding the real email address is by having the person email you back from the anonymous address or asking Craigslist directly (and I doubt Craigslist would give out the real address, unless there was good reason). I’m not quite sure what you mean by digital signature, but you may be able to see the images again by doing a Google Search for the Craigslist URL and viewing Google’s “Cached” version of the page. Sometimes this is a good way of seeing how the page looked in the past. Sorry I couldn’t be of more assistance.
Jason
Awasome, this exactly what i needed!
Jason, in adition, for security/monitoring purposes I also need the script to BCC all the mails it sends/receives/forwards, to an administrator’s emailadress.
How to accomplish that?
Please help! thank you
Kuif
Hi Kuif,
If you’re using phpmailer you should be able to add a BCC by using:
$mail->AddBCC($bcc_email_address, $bcc_name)
Good luck!
Jason
I run a site similar to craigslist, and I have been looking for an easy solution to this for months…. you rule!
I’m also looking for a way to get out of my daily cube so I cant wait to check out the rest of your blog. Thanks for the tip!!
Glad I could help Shawn!
You still need to manually create each anonymous email address each client. How can you set it up so the script can automatically generate one like that of Craigslist?
Hi Ed,
Sorry about that, in hindsight, I forgot to include the details on creating the email accounts.
Because you’re using a catch-all email address you don’t need to create each individual email address. You can have the email addresses be whatever you want and they’ll automatically be routed to the catch-all address where you can act on it with the script above.
For Keys To China, each user gets an email address that starts with “Candidate” and then I throw a random 6-digit number on the end, double check that 6-digit number isn’t being used by anyone else and then assign that to the user.
Let me know if you have any other questions or if something was unclear.
Jason
Thanks a lot. This would be a life saver
I’m so happy to read this. This is the type of manual that needs to be given and not the accidental misinformation that’s at the other blogs. Appreciate your sharing this best doc. Executive Elite, 18a Greycoat Gardens, Greycoat Street, London, SW1P 2QA, 028 2088 0135
With your host, if you use the default phpmailer call (which uses mail() ), with your hosting situation, you’re more than likely going to eat up what are called SMTP RELAYS. Most hosts only allow 100-250 stmp relays per day (which means, they only allow your scripts to send out that many emails per day)
So I switched the transport mechanism to use SMTP instead of the default transport and ran into a problem.
When trying to set the from address, I’m noticing that Gmail ignores what I feed it, and sends the GMAIL mailbox info anyway.
so, this is set in the code:
// for examples sake
$from_email_address=’[email protected]';
$MessageSentFromName = ‘TEST GUY';
$mail->AddReplyTo($from_email_address, $MessageSentFromName);
$mail->SetFrom($from_email_address, $MessageSentFromName);
But when the message is sent, the from is being reset (by gmail I believe).
The message gets sent to the right person, but instead of being from TEST GUY
it ends up coming through as: ME
If I switch the mail server to be sent from another provider I use, this is not an issue, so I’m definitely thinking it’s a GMAIL issue.
Any help anyone? Anyone else have this issue?
Great Stuff! can you please tell me how we can also forward attachments - in addition to the text ?
would be much appreciated.
Hi Sharad,
phpmailer has a function called addattachment that should be able to handle this:
$mail -> AddAttachment(“path/filename.extension”);
Jason
Hi Jason,
thanks for all your help!
This works really nice - but have a nagging issue :
I’m trying to extract the email received as html - and have it forwarded.
however on extracting the email - the version is always text & hence forwarded as text.
even when i have enabled the following:
$mail -> ContentType = ‘text/html'; //Plain email
$mail -> IsHTML(true); //No HTML
anything i am missing ? help is always appreciated
Hi Sharad,
It’s tough to say with so little information, but no, it doesn’t look like you’re missing anything.
Check out this page, he has a nice little tutorial on sending HTML emails: http://www.askapache.com/php/phpfreaks-eric-rosebrocks-phpmailer-tutorial.html
Basically all he does is:
$mail->Body($htmlEmailText); //Save the HTML information as the Body
$mail->isHTML(true); //Set to true
Good luck!
Jason
Hey, thanks for posting this, i have never been to your site before but Google brought me right to your doorstep for the answer i was searching for and i could not be more grateful! I am working on a side business/project that is going to require me to have the craigslist email functionality and this is a life/time saver! thanks for the info!
Hey Raymond,
No problem. I’m glad I could help. Good luck with the project!
Jason
Hi,
Wow! Thanks for this great post… funny this should bring me to your site, when actually you have a great site with all kinds of fun travel stuff, which is my passion. I am SO not a techie! That said, back to the question at hand…
I am curious if the recipient has to have an email address at your domain, or if there is a way to do it so that two people can communicate through my site without either one having an address at my url. (Maybe I missed something, but looks as though this is the case?)
Thanks very much!
Hi Celine,
You’re welcome! I’m glad you enjoyed the post.
No, the recipient can have an email address on any domain. The viewable Email address is the one on your domain and then on the backend, you have a database that links the viewable Email address with the user’s real Email address (which can be anything). If you have any other questions. Let me know!
Thanks,
Jason
GREAT POST!
Just what I was looking for.
Will this also forward attachments? If not, how would that be done.
Thanks
Dan
I got error :
Warning: imap_open() [function.imap-open]: Couldn’t open stream {imap.gmail.com:993/imap/ssl/novalidate-cert}INBOX…
linux env. Do Ineed to have Openssl enable in php.. My hosting company is justhost…
thx
@Dan — Yup, it will forward attachments. phpmailer has a function called addattachment that should be able to handle this:
$mail -> AddAttachment(“path/filename.extension”);
@KB — It looks like your host isn’t giving you access to port 993. Email or call them and see if you can get access.
Jason:
thanx for quick reply.
Justhost told me the port 993 is opened…not blacked
I read
http://groups.google.com/group/comp.lang.php/browse_thread/thread/241e619bc70a8bf4/bd3ae0c6a82409bc?lnk=raot&pli=1
can it be openssl issue …
asking justhost to recompile php with openssl…
what do you think ?
-KB
I doubt it. Have you made sure that imap is enabled for the account that you’re trying to access?
Jason:
I implement anonymous email using
piping way to handle anonymous email , so that the email can be handled immediately ..take a look at my site…
http://www.alicelists.com — will be launch it soon ….
Note: your suggestion is valuable but it may not work on justhost.com in a “sharing environment” or maybe because we paid only only $4.45/month…
instead of using phpmailer to process the “anonymous email… ” I used sendmail.
Hey KB — Thanks for the comment. Site looks great, very clean and interesting. Good luck!
Jason
Hi Jason,
Could you post the instructions for implementing this in a Rails app as well please?
Thanks!
Faisal
Hi Faisal,
Thanks for the comment, but I’m sorry, I’m not familiar with Rails. Once you figure it out, it’d be great if you could come back and give the implementation advice to others. Good luck!
Jason
I love your website. It is great and I will add you to my RSS feeds to follow your progress. I hope to be able to travel someday as well. But about this post…
This was really helpful to me because I am trying to do this, however, the instructions are not for dummies like me.
I created the Google Apps account and set up the email, check.
After several hours researching creating and updating databases, I got it, check.
I can’t find any simple instructions to installing phpMailer. I have Bluehost. At first, I thought it said to copy the code from the file into the php.ini but realized it wasn’t that. But I still don’t understand the instructions. Does it mean that we write an include code to the php.ini file to point it to the phpMail files? And where is the best place to put the phpMail files on our server?
Also, that code that you provided, Where do we put it? Does it go in the class.phpmailer.php file? Will this code be safe from someone reading it, because it will have our Google app passwords on it?
Thank you so much for your time and knowledge.
~ Emily
Hi Emily — Thanks for the comment and the compliments on the site. I’ll try my best to explain here, but to be perfectly honest, it sounds like you may want to take a step back and learn a little more of the basics before jumping into this. To install phpmailer you just upload the files to your server (via FTP). It’s not like a Windows application where you need to run and install something. Both the code I wrote and the include code go in the same file, it goes in a separate php file you create yourself. And don’t worry about the Google app password, all php files are safe.
Good luck!
Jason
Thank you Jason. LOL, basics are good to know. I know html, css and how to use php to create custom wordpress themes. mySQL and using php to connect with databases is new to me. I took the approach, learn as I need it.
With this new project, I am gathering information and putting together the code then I will hire someone to look it over and make sure it will work.
Thank you so much.
hey jason,
awesome tutorial!!!
i got a question though, how come you don’t seem to do anything with smtp at all?
i’m able to connect and read messages just fine, but when i try to do $mail->send(), i get the error “Could not instantiate mail function”. and when i google around, every forum mentions smtp, so i’m wondering if that’s what i’m missing.
thanks!
Hey George — Thanks very much. It’s been a while since I wrote this, but I believe I use imap instead of smtp. Are you getting that error locally or on your server? If it’s local, that sounds right, you won’t have a mail server. If that’s on your server, I couldn’t tell you.
Good luck!
Jason
its was a great script bundles off thanks for auther
Hi Jason,
I couldn’t get it to work. I am not sure what I am doing wrong. I keep getting a Cron error saying something about the server.
I checked to make sure my server had the port open and they do.
I wonder if it is the cron wrong, or maybe the name of my database columns, or installing PHPMailer wrong.
I know you said to just upload the PHPMailer files, but I wonder if I also have to add a “include blah blah” to the php.ini file pointing to the PHPMailer files?
BTW, I have learned so much more since our last comments. Thank you.
Also, let me know if you hire yourself out for this kind of work.
I know this is over 2 years old now, but wanted to say thank you, this was so much simpler than I thought it would be
Awesome Nick — glad it was helpful! Thanks for the comment
Hey Jason,
Came across this posting in an effort to create a website that has the ability to hide users emails, similar to craigslist. This definitely helps a lot moving forward. Many thanks for this post!
Hello
Thank you for giving this Great solution ..