<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Retina Technology Blog &#187; twitter</title>
	<atom:link href="http://www.retina.net/tech/category/twitter/feed" rel="self" type="application/rss+xml" />
	<link>http://www.retina.net/tech</link>
	<description>John Adams' views on emerging technologies, software engineering, and various hacks</description>
	<lastBuildDate>Fri, 16 Sep 2011 09:06:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
	<!-- podcast_generator="podPress/8.8.10.2" -->
	<copyright>2006-2007 </copyright>
	<managingEditor>jna@retina.net (John Adams)</managingEditor>
	<webMaster>jna@retina.net (John Adams)</webMaster>
	<ttl>1440</ttl>
	<image>
		<url>http://www.retina.net/tech/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
		<title>Retina Technology Blog &#187; twitter</title>
		<link>http://www.retina.net/tech</link>
		<width>144</width>
		<height>144</height>
	</image>
	<itunes:subtitle></itunes:subtitle>
	<itunes:summary>John Adams' views on emerging technologies, software engineering, and various hacks</itunes:summary>
	<itunes:keywords></itunes:keywords>
	<itunes:category text="Technology" />
	<itunes:category text="Technology">
		<itunes:category text="Tech News" />
	</itunes:category>
	<itunes:author>John Adams</itunes:author>
	<itunes:owner>
		<itunes:name>John Adams</itunes:name>
		<itunes:email>jna@retina.net</itunes:email>
	</itunes:owner>
	<itunes:block>no</itunes:block>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="http://www.retina.net/tech/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<item>
		<title>Unicorn Power</title>
		<link>http://www.retina.net/tech/unicorn-power.html</link>
		<comments>http://www.retina.net/tech/unicorn-power.html#comments</comments>
		<pubDate>Wed, 31 Mar 2010 01:25:51 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[rubyrails]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/unicorn-power.html</guid>
		<description><![CDATA[Ben Sandofsky and I just put a new post on the Twitter Engineering blog about our transition to Unicorn. http://engineering.twitter.com/2010/03/unicorn-power.html]]></description>
			<content:encoded><![CDATA[<p>Ben Sandofsky and I just put a new post on the Twitter Engineering blog about our transition to Unicorn. </p>
<p><a href="http://engineering.twitter.com/2010/03/unicorn-power.html">http://engineering.twitter.com/2010/03/unicorn-power.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/unicorn-power.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Velocity Preview</title>
		<link>http://www.retina.net/tech/velocity-preview.html</link>
		<comments>http://www.retina.net/tech/velocity-preview.html#comments</comments>
		<pubDate>Thu, 07 May 2009 18:36:12 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[conferences]]></category>
		<category><![CDATA[systems administration]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/?p=212</guid>
		<description><![CDATA[There&#8217;s a small interview with me in today&#8217;s O&#8217;Reilly radar, where I talk about some of the things that I&#8217;ll be presenting as part of my Velocity 2009 talk. You can listen to, and read the transcript here:]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a small interview with me in today&#8217;s O&#8217;Reilly radar, where I talk about some of the things that I&#8217;ll be presenting as part of my Velocity 2009 talk. You can <a href="http://radar.oreilly.com/2009/05/velocity-preview---keeping-twi.html">listen to, and read the transcript here</a>:</p>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/velocity-preview.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Outgoing blacklists, or, stop the bouncing.</title>
		<link>http://www.retina.net/tech/outgoing-blacklists-or-stop-the-bouncing.html</link>
		<comments>http://www.retina.net/tech/outgoing-blacklists-or-stop-the-bouncing.html#comments</comments>
		<pubDate>Sat, 13 Dec 2008 02:14:02 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[systems administration]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[bounce handling]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/?p=175</guid>
		<description><![CDATA[At Twitter, we have many users which sign up for the service and mistype or enter invalid email addresses. Our product group doesn&#8217;t want us to use email verification, and for the most part, we cannot because we accept signups via mobile (through the 40404 SMS short-code.) If we bounce too many messages for any [...]]]></description>
			<content:encoded><![CDATA[<p>At Twitter, we have many users which sign up for the service and mistype or enter invalid email addresses. Our product group doesn&#8217;t want us to use email verification, and for the most part, we cannot because we accept signups via mobile (through the 40404 SMS short-code.)  If we bounce too many messages for any major provider with a clue (think: hotmail, gmail, yahoo&#8230;) they&#8217;ll turn us off. If a user signs up for the service with an invalid email service, there&#8217;s a fair chance that we could be sending email to a dead address.  What do we do?!</p>
<p>There&#8217;s two things. First, on outgoing mail, we convert the address to a special VERP address. An email address of &#8220;user@example.com&#8221; becomes &#8220;twitter-<em>welcome</em>-user=example.com@postmaster.twitter.com&#8221;. We usually replace &#8220;welcome&#8221; with something topical so we can track the origin of the message.</p>
<p>Why <a href="http://en.wikipedia.org/wiki/Variable_envelope_return_path">VERP</a>?</p>
<p>If the mail bounces, the mailer-daemon on the other end will bounce the message back to the <em>postmaster</em> machine, which is a transport method in our inbound Postfix server pool. If an MTA along the transit path destroys the original destination email address, we can recover it from the To: address on the bounce. DJB first devised this for use with qMail, but it works great here.</p>
<p>That server runs a Ruby (originally written in perl) script, that pushes data to an internal API that increments the email address with a <em>bounce score </em>. Get too many points in the bounce score table, and we disable sending to your account. If you change your email address in our database, or ask us to try again, we clear the bounce score. We also clear the bounce score after 30 days or by admin request.</p>
<p>We identify and score bounced emails through the use of a simple regexp based scoring mechanism and/or use the DSN if a Delivery Status Notice is available.  A &#8220;5&#8243; indicates &#8220;hard fail, &#8220;2&#8243; = soft fail, and &#8220;1&#8243; = we don&#8217;t know. Anyone scoring over five is disabled. If it&#8217;s the &#8220;welcome to twitter&#8221; message, we mark it as 10 immediately. Your first mail has to go through, period.</p>
<p>Disabling is accomplished through a <em>reverse blacklist</em> through Postfix&#8217;s <strong>smtp_recipient_restrictions</strong> configuration directive and MySQL via proxymap.</p>
<p>The directives to do this under Postfix 2.5 are pretty simple.</p>
<p>In main.cf, On the central outgoing server(or servers&#8230;), Add:</p>
<pre># bounce handling
bouncehandler_destination_recipient_limit = 1
transport_maps = btree:/etc/postfix/transport

smtpd_delay_reject = yes
smtpd_recipient_restrictions = \
  check_recipient_access mysql:/etc/postfix/reject-bouncing.cf, \
        permit_mynetworks, \
        reject_unauth_destination</pre>
<p>/etc/postfix/reject-bouncing.cf:</p>
<pre>user = your_db_username
password = your_db_password
dbname = your_db_name
hosts = your_db_host
query = SELECT 'DISCARD in_bouncers_table' FROM bouncers WHERE email='%s' AND score &gt;= 5</pre>
<p>In master.cf, on the incoming server, add:</p>
<pre>bouncehandler  unix  -       n       n       -       -       pipe
  flags=DRhu user=nobody argv=/etc/postfix/bouncehandler.pl</pre>
<p>I use the following function to calculate severity of a bounce. It&#8217;s not perfect:</p>
<pre>sub get_severity {
    my ($es) = @_;
    my $body = $es-&gt;body;
    my $subject = $es-&gt;header("Subject");
    my $score = 1;

    # DSN Failures
    if ($body =~ /Action: failed/) {
	$score = 5;
    }

    # check through body of message and try to score the bounce.
    # temp failures.
    if ($body =~ /connection refused|host unreachable|host or domain not found/mi) {
	$score = 5;
    } 

    if ($body =~ /quota|mail(box|folder)* is full/mi) {
	# mailbox full, not as bad, we'll try up to 4 times.
	$score = 2;
    } 

    # wierd temporary failures
    if ($body =~ /(junk mail|spam) try again later/mi) {
	$score = 1;
    }

    # temp.
    return $score;
}</pre>
<p>I leave it to you to write bouncehandler.pl, including the above code, and the database schema. It&#8217;s very simple. Parse the message, create rules, insert/update a record in your database. I used Email::Simple for parsing, and DBI/Mysql for database access.</p>
<p>The DB Schema needs to contain these columns (at a minimum): The email address, a score column, created_at, and updated_at.</p>
<p>My queries look something like this:</p>
<pre># prepare SQL statements for later use
# last times are based on our receipt, not theirs.
$findemail_sth = $dbh-&gt;prepare('SELECT id, score FROM bouncers WHERE email=?');
$insert_sth    = $dbh-&gt;prepare('INSERT INTO bouncers (email,score,updated_at,user_id) VALUES (?,?,now(),?)');
$update_sth    = $dbh-&gt;prepare('UPDATE bouncers SET score=?, updated_at=now(),user_id=? where id=?');</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/outgoing-blacklists-or-stop-the-bouncing.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Obama Wins!</title>
		<link>http://www.retina.net/tech/obama-wins.html</link>
		<comments>http://www.retina.net/tech/obama-wins.html#comments</comments>
		<pubDate>Wed, 05 Nov 2008 06:00:07 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[stuff]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[Scott Beale]]></category>
		<category><![CDATA[Twitter HQ]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/?p=150</guid>
		<description><![CDATA[What a night Tuesday was &#8211; Obama won. Twitter Stayed up. OMG! I&#8217;m in the lower left of this photo. It&#8217;s not the best, but it&#8217;s representative of our collective emotion at Twitter HQ on that historic night! Image Courtesy of Scott Beale, Laughing Squid. The rest of the photos and Scott&#8217;s article Lives here [...]]]></description>
			<content:encoded><![CDATA[<p>What a night Tuesday was &#8211; Obama won. Twitter Stayed up. OMG!</p>
<p>I&#8217;m in the lower left of this photo. It&#8217;s not the best, but it&#8217;s representative of our collective emotion at Twitter HQ on that historic night!</p>
<p><img src="http://farm4.static.flickr.com/3172/3005101582_57964d0743.jpg"></p>
<p>Image Courtesy of Scott Beale, Laughing Squid.</p>
<p>The rest of the photos and Scott&#8217;s article Lives <a href="http://laughingsquid.com/election-night-celebrations-with-twitter-digg-current/">here</a> &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/obama-wins.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

