Flashing a Sprint Nexus S 4G to Verizon

I originally wrote the following post in July 2012 to document how to fully flash a Nexus S 4G from Sprint to Verizon Wireless, but never got to publishing it. I have long since switched away from Verizon Wireless and no longer own any of the phones mentioned, and decided to publish it for what it’s worth.

If you’re interested in the high-level view of how CDMA phones are programmed, check out my previous article Carrier Programming on CDMA Android Phones.


This is a guide for flashing a Sprint Samsung Nexus S 4G to a standard Verizon monthly plan, and voice, texting and 3G data will all be fully functional. This method will likely also work on many other phones, especially Samsung ones, and should theoretically work just file on any ROM as well.

Note that this procedure entails ESN cloning, which may be illegal in your region. Please make sure you have an understanding of all applicable laws before proceeding. The author of this guide cannot be held responsible for any legal infractions that may ensue. Finally, you are solely responsible for any consequences of your actions as a result of following this guide. While I believe it to be quite safe, I cannot guarantee you that this process will not brick your devices or start a zombie apocalypse.

Requirements and Setup

We will need the following before starting:

  • A currently active Verizon Wireless Android phone and plan. Please beware that not all phones will work; many phones do not allow us to extract all the information we need for this process. For instance, my Motorola Droid 3 did not work, and I had to purchase and activate an HTC Incredible for this. This phone will be our donor phone.

  • A rooted Samsung Nexus 4G.

  • A computer running a recent version of Windows, with at least 2 USB ports.

  • 2 MicroUSB cables.

In addition, we need the following software:

  • USB diagnostic drivers for your donor phone. These vary by manufacturer and their configuration may be quite complex; search online for how to set up yours. For HTC phones, download and install HTC Sync from HTC’s website (archived here).

  • USB diagnostic drivers for the Nexus S 4G. The easiest way is to download and install PdaNet (archived here). We don’t actually need the functionality of PdaNet, but it happens to bundle the drivers we need. Select Samsung when prompted for the manufacturer of our phone.

  • QPST and QXDM (archived here). These are internal Qualcomm tools; we will use them to clone the MEID of the donor phone.

  • DFS (archived here). This is a third-party tool for working with CDMA phones. The demo version will suffice.

Step 1: Preparation

First, make sure the donor phone is fully activated and that calls, text and data are all fully functional.

Now, find the HEX MEID of the donor phone. On the HTC Incredible, this can be found under Settings → About Phone → Phone Identity. On most Android phones, this is under Settings → About Phone → Status. It is also usually printed on a label underneath the phone battery. This should be 14 digits and usually begins with A00000.

Now put the donor phone in airplane mode.

We will next connect both phones to the computer in diagnostic mode.

  • On the Nexus S 4G, dial *#*#8778#*#*, then select MODEM under USB. Connect the Nexus S 4G to the computer. If drivers were installed correctly, you should now see a SAMSUNG Mobile Modem Diagnostic Serial Port (WDM) under Ports (COM & LPT) in Windows’s Device Manager. Note down the port number of the Nexus S 4G; we will assume COM4 for convenience.

  • On the HTC Incredible, dial ##3424#, hit Call, connect it to the computer, then follow the instructions in this thread with Device Manager. If everything goes well you should now see a HTC Diagnostic Interface under Ports (COM & LPT) in Device Manager. Note down the port number of the HTC Incredible; we will assume COM11 for convenience.

After confirming that both phones show up under Ports (COM & LPT), run QPST Configuration and hit Add New Port…. You should see both phones on the left. Select one and hit OK. Then repeat for the other phone.

Step 2: Cloning

We will now clone the MEID of the donor phone onto the target phone. Open QXDM Professional. Select Options → Communications…. For Target Port, select the port corresponding to the Nexus S 4G, say COM4, and hit OK. Then in the text box labeled Command, type the following:

Password 01F2030F5F678FF9

Hit Enter. You should see Password Result = Correct at the bottom of the Command Output window.

Now in the Command text box, type the following, replacing <MEID> by the hex MEID of the donor phone:

RequestNVItemWrite meid 0x<MEID>

Hit Enter. You should see it repeat back the MEID to you. Type RequestNVItemRead meid followed by Enter to make sure the write happened.

Close QXDM Professional and reboot the Nexus S 4G. Rebooting the target phone after writing a new MEID is essential! If prompted, do NOT go through the activation process on the Nexus S 4G. Just select Skip when possible.

Step 3: Reset SPC

In order to program the Nexus S 4G, we need to obtain or reset the SPC code (also known as the MSL) of the phones. If you already know the SPC code for your phones and would rather not reset the SPC code, you can skip this step.

Open QXDM Professional again. Go through Options → Communications and make sure the Target Port is still COM4. Hit OK. In the command text box, type the following two lines, each followed by an Enter:

Password 01F2030F5F678FF9
RequestNVItemWrite sec_code 000000

If this is successful, the SPC on the Nexus S 4G will have been reset to 000000. Repeat for the donor phone (in our example, on COM11).

Close QXDM Professional after done. All QPST / QXDM programs must be closed before proceeding, or DFS will complain.

Step 4: Programming CDMA Chipset

Launch DFS. Click Ports on the top left. In the dialog box, double-click on each port representing our phones, in our case, COM4 and COM11, and close the dialog box. Now make sure the SPC text box above reads 000000 (or if you chose not to reset the SPC, whatever your SPC is). Type 01F2030F5F678FF9 into the Pwd text box.

Step 4.a: Basic CDMA settings

Let’s now copy basic CDMA settings from the donor phone to the target phone. In the drop-down menu next to Ports, select the donor phone (COM11). Switch to the Programming tab and the NAM tab under it. Click the SPC and Pwd buttons to send the SPC and NV password to the phone to unlock it. Then hit Read beneath Network identification. The text fields below should be populated by information from the donor phone. Now select COM4 in the drop-down menu next to Ports, click SPC and Pwd, then click Write beneath Network identification.

Step 4.b: PRL

Now, let’s copy over the PRL (or Preferred Roaming List - essentially a database of tower locations). Again, select COM11 under Ports and click Read under PRL towards the right. Then select COM4 under Ports and click Write under PRL.

Step 4.c: 2G Data settings

Now go to the next tab, Data. Select COM11 and hit Read. Switch to COM4 and hit Write. If you observe errors in the log window in the bottom, and / or no information shows up in the Pwd boxes under PPP and HDR AN Long, your donor phone doesn’t support the extraction of some data passwords, and you will have to try a different donor phone.

Step 4.c: 3G Data settings

We do the same with Mobile IP. Select COM11 and hit Read. Switch to COM4 and hit Write. Then hit Write current profile settings. Again, if you encounter errors, or no information shows up under AAA Shared secret and HA Shared Secret, you will have to try a different donor phone.

Finally, we need to copy over a file containing a secret key used to establish a 3G connection. Go to the EFS tab towards the top. Select COM11 and hit Read EFS. Click the "+" sign of the root folder on the left and then the "+" sign next to the DMU folder and you should see a file called 10.key. Right-click on this file and hit Save…. Save this file somewhere on your hard drive. Now switch to COM4 and hit Read EFS again. Select the root folder on the left, type /DMU under Path (57 max) on the right and hit Add Item to create a folder named DMU on the Nexus S 4G. Then select DMU on the left, click on the check box named I want to add file from PC, and select the 10.key file we just saved. Then hit Add Item to upload the 10.key file to /DMU/10.key.

The programming is now done. Close DFS, select OK and OK again when prompted whether to send a mode reset to the phone. The Nexus S 4G will now reboot.

Step 5: Programming Android

We will now modify some Android system files to Verizon settings. This step will need to be repeated whenever you flash a new ROM on the Nexus S 4G in the future.

1-click programming app

I have built a 1-click Android application that automates this step; you can find it here. It requires root as it will need to modify system files. Install the application and click the button in the middle. When the process finishes, you will be prompted to reboot. Simply reboot your phone and you’re all set; you may uninstall the app, or you could keep it around for when you update to a new ROM.

If the 1-click app does not work for you, or if you want more control over what it does, follow the steps below. You do not need to do any of the following if you already used the app above.

Step 5.a: Fix voice calling

This is required to enable calls on Verizon. On the Nexus S 4G, connect to WiFi and install ES File Explorer from the Play Store. Then go to Menu → Settings and check Up to Root, Root Explorer, and Mount File System. Allow it to use superuser privileges if asked. Then navigate to /system and open build.prop with ES Note Editor. Find the following two lines:


Change them to read:


Then add a line below (or anywhere in the file) that says:


Hit Menu → Save and then Back to exit.

Step 5.b: Fix roaming

This step tells Android to treat the Verizon network as the home network. It sets the roaming status to "Not roaming", removes the triangular roaming indicator in the status bar and changes the displayed name of the current network to "Verizon Wireless".

Now navigate to /system/framework and copy framework-res.apk onto your computer - you can use adb or email it to yourself or whatever (you have to copy it to the internal SD card before you can email it though). Once on the computer, rename it framework-res.zip (yes, an APK is just a zip archive) and use your favorite program to replace the file res/xml/eri.xml inside it with the one at this link. Now rename it back to framework-res.apk, copy it back onto the Nexus S 4G (using adb or whatever) and use ES File Explorer to overwrite the existing /system/framework/framework-res.apk with it.

Step 5.c: Add Verizon APNs

This last step sets up Verizon APNs that enable web and MMS. Use ES File Explorer or any other tool to replace /system/etc/apns-conf.xml with the one at this link.

Step 6: Reboot & PROFIT

The Nexus S 4G should now be a fully functional Verizon Wireless phone. If you are curious about what each of the steps means, you’re welcome to check out my previous article Carrier Programming on CDMA Android Phones for a high-level view of how CDMA phones are programmed.

While your mileage may vary, I hope the above information have been of help. Since I no longer use Verizon Wireless and no longer own any of the phones mentioned above, please take all this information with a grain of salt.

Good luck, and happy hacking!

Setting Up DKIM And SRS In Postfix

In my previous post Custom Domain E-mails With Postfix And Gmail: The Missing Tutorial, we set up a Postfix mail server on a custom domain that integrates seamlessly with Gmail.

However, the tutorial skipped two important security standards that will help prevent e-mails routed through our server from being marked as spam: DKIM and SRS. This article will show you how to add support for DKIM and SRS to a Postfix server.

Similar to the previous tutorial, we will assume a Ubuntu server in our examples.

Step 1: DKIM

DKIM, short for DomainKeys Identified Mail, is a mechanism for

  1. A sender e-mail program to sign an outgoing e-mail message, and

  2. A recipient e-mail program to verify said signature.

More concretely, let’s say Gmail receives an e-mail message from myserver.example.com. DKIM allows Gmail to verify that the e-mail was indeed sent by the designated e-mail server program on myserver.example.com, and not by, say, a virus running on myserver.example.com or a malicious user who happens to have access to myserver.example.com.

We will use OpenDKIM for this tutorial. To install OpenDKIM on Ubuntu:

$ sudo apt-get install opendkim opendkim-tools


Edit /etc/opendkim.conf to match the following:

# OpenDKIM config.

# Log to syslog
Syslog                  yes
SyslogSuccess           yes
LogWhy                  yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask                   002

Mode                    sv
PidFile                 /var/run/opendkim/opendkim.pid
UserID                  opendkim:opendkim
Socket                  inet:[email protected]

Canonicalization        relaxed/simple
SignatureAlgorithm      rsa-sha256

# Sign for example.com with key in /etc/opendkim.d/mail.private using
# selector 'mail' (e.g. mail._domainkey.example.com)
Domain                  example.com
KeyFile                 /etc/opendkim.d/mail.private
Selector                mail

ExternalIgnoreList      refile:/etc/opendkim.d/TrustedHosts
InternalHosts           refile:/etc/opendkim.d/TrustedHosts

You can check out a detailed explanation for the meaning of each option with man opendkim.conf.


Create the directory /etc/opendkim.d and put the following in /etc/opendkim.d/TrustedHosts. This instructs the OpenDKIM server to sign e-mails delivered by any server matching these expressions (such as myserver_2.example.com).


DKIM keys

Now, let’s generate our DKIM signing keys:

$ cd /etc/opendkim.d
$ sudo opendkim-genkey -s mail -d example.com

This will produce two files in /etc/opendkim.d: our private key, mail.private, and our public key, mail.txt.

We should make sure only OpenDKIM can read the private key, so that a malicious program or user on the same server won’t be able to forge our signature:

$ chmod 600 mail.private
$ chown opendkim:opendkim mail.private

DKIM public key DNS record

The next step is to publish our public key through DNS, so that any recipient e-mail program can verify our signature. If we look at our public key mail.txt generated in the previous step, it should look like something like this:

mail._domainkey IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=<alphabetical soup>" )  ; ----- DKIM key mail for example.com

Create the following TXT DNS record for example.com (how to update DNS records will depend on the DNS hosting provider):

  • Name: mail._domainkey.example.com

  • Value: v=DKIM1; k=rsa; p=<alphabetical soup>

where <alphabetical soup> is the public key found in mail.txt after p=. Note that DNS records will take a while (depending on our provider, up to a day) to propagate.

OpenDKIM server

We can now start the OpenDKIM server with

$ sudo /etc/init.d/opendkim start


The last step is to tell Postfix to use OpenDKIM to sign outgoing e-mail messages. Add the following to /etc/postfix/main.cf:

# Milter settings.
milter_protocol = 2
milter_default_action = accept
# OpenDKIM runs on port 12301.
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301

If you already have other milters configured (such as SpamAssassin), simply add inet:localhost:12301 to your existing smtpd_milters and non_smtpd_milters lines, prefixed by a comma.

Let’s now restart Postfix with the new configuration:

$ sudo postfix reload

…and we’re done!

Step 2: SRS

SRS, short for Sender Rewriting Scheme, is a standard for including forwarding / relay information in a forwarded / relayed e-mail message.

For example, suppose [email protected] sends an e-mail to [email protected], and our Postfix server on myserver.example.com forwards this e-mail to [email protected]. SRS allows our Postfix server on myserver.example.com to attach a virtual sticky note on the e-mail message explaining this situation to Gmail. Otherwise, Gmail might become suspicious of why myserver.example.com is producing messages that purport to come from hotmail.com, which spammers and phishers are wont to do.

We will use PostSRSd to implement SRS in our Postfix server. It works out of the box with Postfix and is a breeze to set up, but unfortunately is not included in the official Ubuntu / Debian package repositories.


Let’s build and install OpenSRSd from source:

# Dependencies.
$ sudo apt-get install unzip cmake

# Download and extract source code from GitHub.
$ cd /tmp
$ curl -L -o postsrsd.zip \
$ unzip postsrsd.zip

# Build and install.
$ cd postsrsd-master
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/usr ../
$ make
$ sudo make install

The default config provided by PostSRSd (/etc/default/postsrsd) will pretty much work out of the box for our case.

The install script will also conveniently install an Upstart script for PostSRSd. Let’s start it now:

$ sudo service postsrsd start


Finally, we configure Postfix to use PostSRSd. Add the following to /etc/postfix/main.cf:

# PostSRSd settings.
sender_canonical_maps = tcp:localhost:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:localhost:10002
recipient_canonical_classes= envelope_recipient,header_recipient

And restart Postfix with the new configuration:

$ sudo postfix reload

That’s it!

Custom Domain E-mails With Postfix and Gmail: The Missing Tutorial

Custom domain e-mail addresses, like [email protected], are cool and professional-looking. Would you want to e-mail potential clients as [email protected]?

On the other hand, Gmail has great reliability, speed, spam filtration, and app support. Wouldn’t it be great if we could send and receive e-mail as [email protected], but right from the comfort of our Gmail account?

Today, if we want to use Gmail to send and receive e-mails on a custom domain, we have a couple of options:

  • Google Apps for Work is Google’s own offering. It’s simple to set up and manage, but it’s pretty pricey at $5/mo per user, especially if we don’t need the bundled collaborative features like Google Docs and Calendar.

  • Third-party services could get the job done at a lower price point; for example, Pobox offers plans starting at $20/yr. The downside is that we will have to trust another organization with our e-mail.

  • Set up our own e-mail forwarding server. It’s fairly easy (if we follow this guide :) and if we already have shared / dedicated hosting or a VPS, this is basically free and gives us total control over our e-mail.

If you want to host custom domain e-mails in Gmail without paying for Google Apps or a third-party service, this tutorial is for you. It will show you how to quickly set up you own e-mail forwarding / relay server, and how to integrate it seamlessly with Gmail.


For this tutorial, we’ll assume we have access to:

  • VPS or shared / dedicated hosting, with a dedicated IP address and capable of listening on ports 25 and 587. We will use a Ubuntu server for the examples.

  • DNS records for our domain. How DNS records are manipulated depends on the DNS hosting provider (or DNS server configuration).

We’ll assume

  • We have a domain example.com;

  • We have a server myserver.example.com;

  • We want to use the Gmail account [email protected] to manage [email protected].

Step 1: DNS Setup

The first step in setting up our e-mail forwarding server is to add MX, PTR and SPF DNS records for our server. This is really important as many e-mail providers, in order to prevent spam, will refuse to talk to mail servers without proper MX, PTR and SPF records set up. How to update DNS records will depend on the DNS hosting provider.

The following is what we need:

  • An MX record for example.com, pointing to myserver.example.com.

    This tells the world that e-mails to <whatever>@example.com should be delivered to the server myserver.example.com.

  • An A record for myserver.example.com, pointing to the IP address of our server.

  • A PTR (reverse DNS) record mapping the IP address of our server to myserver.example.com.

    This allows Gmail to verify the legitimacy of our server via its IP when Gmail receives a forwarded e-mail from it.

  • A TXT record, with key example.com and value v=spf1 mx ~all.

    This is an SPF record; it tells Gmail that the servers specified in the MX records of example.com, in this case only myserver.example.com, are allowed to send e-mails purporting to be from <whatever>@example.com. All other servers attempting to do the same will be rejected. This should be a sane default value, but feel free to custom it as you like.

DNS records will take a while (depending on our provider, up to a day) to propagate. Until they do, e-mails forwarded by our new e-mail server may get marked as spam or rejected outright.

Step 2: Receiving E-mail

We’ll first set up an e-mail forwarding server which will let we receive e-mails sent to our domains.

We will use Postfix as the e-mail server. Let’s start by installing the necessary packages. We will assume a Ubuntu server in the examples below; if you’re using a different distribution, please consult your distribution’s documentation for the right commands.

$ sudo DEBIAN_FRONTEND=noninteractive apt-get install postfix

In the above command, we skip the debconf configuration UI with DEBIAN_FRONTEND=noninteractive as we will edit the configuration files directly.


Open up /etc/postfix/main.cf in your favorite editor. This file will come pre-populated with a bunch of config options and comments. Replace the contents of the file with the following (you can comment out the original contents for reference):

# /etc/postfix/main.cf

# Host and site name.
myhostname = myserver.example.com
mydomain = example.com
myorigin = example.com

# Virtual aliases.
virtual_alias_domains = example.com
virtual_alias_maps = hash:/etc/postfix/virtual

The first few lines are pretty straightforward; they tell Postfix how to identify itself to the world. The last two lines tell Postfix to forward e-mails sent to <whatever>@example.com to another e-mail provider (Gmail), and that the forwarding is configured in the database file /etc/postfix/virtual.


Let’s now open up /etc/postfix/virtual and fill in our forwarding configuration:

# /etc/postfix/virtual

# Forwarding mapping, one from-to address pair per line. The format is:
#     <forward-from-addr> <whitespace> <forward-to-addr>
[email protected]        [email protected]

We can add as many forwarding rules as you want, one on each line. We can use any number of tabs / whitespaces between the forward-from and forward-to addresses.

Update lookup table

It turns out that Postfix doesn’t actually read /etc/postfix/virtual (surprise!); instead, what it reads is a lookup table generated from it. So, let’s generate the lookup table from our /etc/postfix/virtual:

$ sudo postmap /etc/postfix/virtual

Note: we must re-run this command every time we modify /etc/postfix/virtual!

(Re)start Postfix

It’s now time to (re)start Postfix with our new configuration:

$ sudo postfix start
$ sudo postfix reload


We should test our brand-new Postfix server by sending an e-mail to our forward-from address. You might want to check out these tutorials for testing directly with the telnet command.

If you received the e-mail in your Gmail inbox, congratulations! Otherwise, check the Postfix logs at /var/log/mail.log (or with journalctl -u postfix if using Systemd) for errors. The most likely cause of issues is that DNS records have not propagated yet, in which case we’re likely to see a "rate limited" or "rejected for spam" type error message.

If we only want to receive but don’t care about sending e-mails as [email protected], then this is all we need.

Otherwise, let’s move on to configuring Postfix to support sending e-mails from Gmail.

Step 3: Sending E-mail

Gmail requires a relay server (a server that will send e-mails to their destination on behalf it) to speak TLS, which protects the communication between Gmail and the relay server.

We will use Cyrus SASL for this task. To install:

$ sudo apt-get install sasl2-bin libsasl2-modules

User name & password

Open relays are a terrible idea. We want to protect our e-mail server with a user name and password so that it will let Gmail send e-mails through it, but block spammers and other evil actors.

Cyrus SASL supports several backends for storing user names and passwords, including MySQL and PAM. However, we will go with the simplest backend — a plain database file.

Let’s create the user name / password database file in the default location /etc/sasldb2, with a single user named smtp (we can change the user name to anything we want):

$ sudo saslpasswd2 -c -u example.com smtp

Verify with:

$ sudo sasldblistusers2

Now, we make sure only Postfix can read this file:

$ sudo chmod 400 /etc/sasldb2
$ sudo chown postfix /etc/sasldb2

Lastly, we tell Cyrus SASL to use the file-based database to authenticate. Create the file /etc/postfix/sasl/smtpd.conf:

pwcheck_method: auxprop
auxprop_plugin: sasldb
log_level: 7

SSL Certificate

We need an SSL certificate to enable TLS. While a proper SSL certificate signed by a Certificate Authority (CA) can be pricey, it turns out that a simple self-signed certificate suffices and works just fine.

So, let’s generate one.

  1. Generate an RSA private/public key pair. Note that you MUST supply a password to this command; the password will be removed in step 3.

    $ openssl genrsa -des3 -out example.key 1024
  2. Generate a Certificate Signing Request (CSR). Make sure to enter myserver.example.com when prompted for the "Common Name".

    $ openssl req -new -key example.key -out example.csr
  3. Remove RSA private/public key password.

    $ mv example.key example.key.orig
    $ openssl rsa -in example.key.orig -out example.key
  4. Generate a self-signed certificate. In the example, the generated certificate will be valid for 10 years.

    $ openssl x509 -req \
        -days 3650 -in example.csr -signkey example.key -out example.crt
  5. Create a PEM file.

    $ cat example.crt example.key > example.pem
  6. Move and protect the PEM file.

    $ sudo mv example.pem /etc/postfix/example.pem
    $ sudo chmod 400 /etc/postfix/example.pem
    $ sudo chown postfix /etc/postfix/example.pem

Note: Make sure to protect the generated private key and certificate with care!

Relay server

The final step is to configure Postfix to enable relaying of e-mail on behalf of Gmail.

Let’s open up /etc/postfix/master.cf. This file should already contain a bunch of config options, some of which are commented out. Uncomment the lines starting with submission and edit them to match the following:

submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=may
  -o smtpd_tls_cert_file=/etc/postfix/example.pem
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

A Postfix restart is due after all these changes:

$ sudo postfix reload

If all went well, you should see Postfix serving a relay server, protected by our user name and password in /etc/sasldb2, on port 587.

Step 4: Configure Gmail

Finally, let’s log in to Gmail and tell it about our brand new server. (Note that the new Inbox UI does not yet support all the settings available in the legacy interface at the time of writing, so these instructions apply to the legacy interface.)

Let’s go to Settings > Accounts and Import and click Add another email address you own.

In the dialog that pops up, fill in our target e-mail address and click Next Step.
In the next dialog, enter the address of our e-mail server (myserver.example.com), and the user name and password we set up using saslpasswd2 above. Make sure the user name is suffixed with our domain name (so [email protected] rather than just smtp). Check that the correct port (587) and the correct security protocol (TLS) are selected, then click Add Account.
If all goes well, we should see a dialog like the following:
And we should receive an e-mail, forwarded by our mail server set up in the first part, to our [email protected] address. Click on the link inside the e-mail and we’re done!

Now, in any e-mail compose / reply window, you should be able to select [email protected] in the drop-down list next to "From". Congrats!

If, on the other hand, you see an error like the following:

You should check the Postfix logs at /var/log/mail.log (or with journalctl -u postfix if using Systemd) for any errors.

[Optional] Step 5: Setup DKIM and SRS

DKIM, short for DomainKeys Identified Mail, is e-mail validation system for preventing e-mail spoofing. Google recommends setting up DKIM; if we don’t, the e-mail messages that we forward to Gmail have a higher probability of getting marked as spam.

SRS, short for Sender Rewriting Scheme, is a relatively new standard that e-mail forwarding servers are recommended to adopt, and it also helps reduce the likelihood of our forwarded e-mail messages getting marked as spam.

Thus, while technically optional, it’s a good idea to configure our Postfix server to support both these standards. See my follow-up tutorial on Setting Up DKIM And SRS In Postfix for a detailed step-by-step guide.


In this post, we have set up a Postfix e-mail server that accomplishes the following:

  • E-mails sent to [email protected] is received by Postfix on myserver.example.com port 25, and forwarded to [email protected];

  • Gmail will let you select [email protected] as a "from" address when composing / replying to an e-mail, and will relay such e-mails through Postfix on myserver.example.com port 587 using a configured user name / password combination.

I hope you found this guide useful, and if you have any thoughts / questions, you’re more than welcome to leave a comment below. Cheers!

How To Add Custom Build Steps and Commands To setup.py

A setup.py script using distutils / setuptools is the standard way to package Python code. Often, however, we need to perform custom actions for code generation, running tests, profiling, or building documentation, etc., and we’d like to integrate these actions into setup.py. In other words, we’d like to add custom steps to setup.py build or setup.py install, or add a new command altogether to setup.py.

Let’s see how this is done.

Adding Custom setup.py Commands and Options

Let’s implement a custom command that runs Pylint on all Python files in our project. The high level idea is:

  1. Implement command as a subclass of distutils.cmd.Command;

  2. Add the newly defined command class to the cmdclass argument to setup().

To see this in action, let’s add the following to our setup.py:

import distutils.cmd
import distutils.log
import setuptools
import subprocess

class PylintCommand(distutils.cmd.Command):
  """A custom command to run Pylint on all Python source files."""

  description = 'run Pylint on Python source files'
  user_options = [
      # The format is (long option, short option, description).
      ('pylint-rcfile=', None, 'path to Pylint config file'),

  def initialize_options(self):
    """Set default values for options."""
    # Each user option must be listed here with their default value.
    self.pylint_rcfile = ''

  def finalize_options(self):
    """Post-process options."""
    if self.pylint_rcfile:
      assert os.path.exists(self.pylint_rcfile), (
          'Pylint config file %s does not exist.' % self.pylint_rcfile)

  def run(self):
    """Run command."""
    command = ['/usr/bin/pylint']
    if self.pylint_rcfile:
      command.append('--rcfile=%s' % self.pylint_rcfile)
        'Running command: %s' % str(command),

        'pylint': PylintCommand,
    # Usual setup() args.
    # ...

Now, running python setup.py --help-commands will show:

Standard commands:
Extra commands:
  pylint: run Pylint on Python source files

We can now run the command we just defined with:

$ python setup.py pylint

…or with a custom option:

$ python setup.py pylint --pylint-rcfile=.pylintrc

To learn more, you can check out documentation on inheriting from distutils.cmd.Command as well as the source code of some built-in commands, such as build_py.

Adding Custom Steps to setup.py build

Let’s say we are really paranoid about code style and we’d like to run Pylint as part of setup.py build. We can do this in the following manner:

  1. Create a subclass of setuptools.command.build_py.build_py (or distutils.command.build_py.build_py if using distutils) that invokes our new Pylint command;

  2. Add the newly defined command class to the cmdclass argument to setup().

For example, we can implement the following in our setup.py:

import setuptools.command.build_py

class BuildPyCommand(setuptools.command.build_py.build_py):
  """Custom build command."""

  def run(self):

        'pylint': PylintCommand,
        'build_py': BuildPyCommand,
    # Usual setup() args.
    # ...

For more examples, I encourage you to check out the setuptools source code.

Announcing AsciiDocLIVE

I am very pround to announce the alpha launch of AsciiDocLIVE (https://asciidoclive.com/), a free online AsciiDoc editor with instant live preview, syntax highlighting, and more!

The Idea

The idea for AsciiDocLIVE struck me one day while writing a blog post. Being a fan of AsciiDoc, I use AsciiDoc for this blog, but the repetitive cycle of edit-compile-preview is pretty tedious. I realized that there wasn’t a good AsciiDoc editor that supported live previews (like Dillinger or Markable for Markdown). So, I hacked up a quick prototype in my spare time, and AsciiDocLIVE was born!


Features included in this alpha launch:

  • Instant live preview: type in the left pane, see rendered result in the right pane.

  • Smart error messages: errors generated by the AsciiDoc compiler are displayed and linked to the offending line in the source text.

  • Syntax highlighting

To be available soon:

  • Saving documents

  • Importing from and exporting to Dropbox / Google Drive