postfix "User doesn't exist" but user does exist

I am having a strange situation which I could not find elsewhere. When I send mail to rcook on my local machine, I'm seeing this in the syslog:

Feb 16 20:27:14 linode postfix/pickup[1305]: 326CC4463F: uid=0 from=<root>
Feb 16 20:27:14 linode postfix/cleanup[1524]: 326CC4463F: message-id=<[email protected]>
Feb 16 20:27:14 linode postfix/qmgr[1306]: 326CC4463F: from=<[email protected]>, size=302, nrcpt=1 (queue active)
Feb 16 20:27:14 linode postfix/lmtp[1531]: 326CC4463F: to=<[email protected]>, orig_to=<rcook>, relay=linode.example.net[private/dovecot-lmtp], delay=0.06, delays=0.04/0.01/0.01/0.01, dsn=5.1.1, status=bounced (host linode.example.net[private/dovecot-lmtp] said: 550 5.1.1 <[email protected]> User doesn't exist: [email protected] (in reply to RCPT TO command))
Feb 16 20:27:14 linode postfix/bounce[1533]: 326CC4463F: sender non-delivery notification: 3C71844643
Feb 16 20:27:14 linode postfix/qmgr[1306]: 326CC4463F: removed

It looks like "rcook" is being turned into "[email protected]" by postfix. I am using mysql lookups for postfix, per my main.cf file:

#Virtual domains, users, and aliases
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

I have to add a user, [email protected] to my /etc/postfix/mysql-virtual-mailbox-maps.cf file. Then rcook gets mail in /var/mail/rcook destined for rcook. In other words, sending mail to 'rcook' gets turned into '[email protected]' which then gets delivered back to 'rcook' I'm hoping someone here can clear up what's going on.
It looks as though rcook is a real mailbox:

root@linode (~ ): postmap -q rcook mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf 
1

and

root@linode (~ ): ls /var/mail/rcook
[Airmail]                           dovecot-uidvalidity
* amazon and ebay sales             dovecot-uidvalidity.54e27e23
Apple Mail To Do                    Drafts
etc etc etc lots of mailboxes... 

[email protected] maps to rcook:

root@linode (~ ): postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-alias-maps.cf 
rcook

But this fails, unless I add a virtual_users entry for [email protected]:

date | mail -s 'testing' rcook

My question is, why is rcook getting mapped to [email protected]? I'm thinking it has something to do with the $mydomain value in the postfix world, but I don't know how that's getting set.

root@linode (~ ): postconf | grep mydomain
append_dot_mydomain = no
mydomain = example.net

Here is my postfix non-defaults:

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
config_directory = /etc/postfix
inet_interfaces = all
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
mydestination = localhost
myhostname = linode.example.net
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
myorigin = /etc/mailname
readme_directory = no
recipient_delimiter = +
relayhost =
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = private/auth
smtpd_sasl_type = dovecot
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/dovecot/dovecot.pem
smtpd_tls_key_file = /etc/dovecot/private/dovecot.pem
smtpd_use_tls = yes
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp

There is nothing mentioning example.net anywhere in /etc/dovecot/. What's going on here? I should mention that if I do add a user [email protected] to my virtual_users, all is well. I just am mystified as to what's happening under the hood as it were, and why this user is needed, since it's just an alias.

Here is what happens in the log when I add '[email protected]' to my virtual_users mapping:

Feb 17 10:35:55 linode postfix/pickup[8804]: 3D785901CA: uid=0 from=<root>
Feb 17 10:35:55 linode postfix/cleanup[9231]: 3D785901CA: message-id=<[email protected]>
Feb 17 10:35:55 linode postfix/qmgr[1619]: 3D785901CA: from=<[email protected]>, size=326, nrcpt=1 (queue active)
Feb 17 10:35:55 linode dovecot: lmtp(9262, [email protected]): IX33DwuK41QuJAAAmhsNrQ: msgid=<[email protected]>: saved mail to INBOX
Feb 17 10:35:55 linode postfix/lmtp[9233]: 3D785901CA: to=<[email protected]>, orig_to=<rcook>, relay=linode.example.net[private/dovecot-lmtp], delay=0.03, delays=0.01/0/0.01/0.01, dsn=2.0.0, status=sent (250 2.0.0 <[email protected]> IX33DwuK41QuJAAAmhsNrQ Saved)
Feb 17 10:35:55 linode postfix/qmgr[1619]: 3D785901CA: removed

Let met tell you the secret of email delivery process in linux, featuring sendmail binary and postfix.

When your run

date | mail -s 'testing' rcook

you tell sendmail to send email to rcook, a recipient address without domain parts to postfix. Because you have parameter append_at_myorigin = yes (default value), then postfix will add domain parts to recipient address. The appended domain was controllable via parameter myorigin. In your case, looks like the content of /etc/mailname was example.net.

That's explain why postfix modified your recipient address to [email protected]. Let's continue the story...

Now, postfix must decide where the email should go. First, postfix will lookup virtual_alias_maps to find out whether this email should aliased or not. Because you have defined [email protected] aliased to rcook, then postfix will alising your email to rcook.

But wait, the alias target doesn't have domain parts, so where it go? The answer was lied in this man page and this answer. The short explanation is the postfix appended alias target rcook with myorigin (again). So, our alias target was transformed to [email protected].

But it'll creating looping, right? The email was aliasing to himself?

Fortunately, postfix was intelligent enough to avoid it. Because [email protected] has satisfied these conditions

  • it was already aliased
  • example.net was defined in virtual_mailbox_domains

then the postfix will lookup [email protected] in virtual_mailbox_maps.

Unfortunately, it doesn't find it in your first case, so postfix will bounced it. When you add the entry on virtual_mailbox_maps postfix will happily store it via dovecot LMTP services.

References:

man 5 postconf


One last point I should mention in case someone is confused as I was, about why the mail ultimately gets put into /var/mail/rcook/ when postfix changed "rcook" to "[email protected]". This happens because in /etc/dovecot/conf.d/10-mail.conf I have this:

mail_location = maildir:/var/mail/%n:LAYOUT=fs 

which strips off the domain name. Once @masegaloeh gave his excellent answer I was able to figure out this final piece.