Configuring Out Of Office in a POC Setup
From Zarafa wiki
When setting up a Zarafa POC, it may very well happen that you only want a few users running on the Zarafa system and the rest of the users keep using their Exchange environment. Some mail routing issues can popup when creating such a setup. This article will explain some issues and how to overcome them.
Let's say we have a total amount of 500 users, and we will run the POC with 50 users:
Exchange Zarafa 192.168.0.1 192.168.0.2 ============== ================== user_1 - user_450: LOCAL user_451 - user_500: POC users -----------> user_451 - user_500 FORWARD
The mail for the 50 POC users will be forwarded to the Zarafa server, this needs to be configured within Exchange.
We also assume in our setup that Postfix is being used as MTA on the Zarafa server, however the principle stays the same for any other MTA.
Reaching ALL Users
Let's say that our mail domain is: example.com
Both the Echange server and the Zarafa server need to be aware of the same mail domain. This means that both servers will accept mail for that domain. But in the POC we need the whole company to be able to send emails to each other. We can simply do that by telling the zarafa-spooler to send emails out to the Exchange server.
In /etc/zarafa/spooler.cfg set:
smtp_server = 192.168.0.1
This will create the following situation:
- An Exchange user is able to reach another Exchange user. Path:
Exchange -> Exchange
- An Exchange user is able to reach a Zarafa POC user, because emails to those users are forwarded to Zarafa. Path:
Exchange -> Forward to Zarafa -> Postfix -> Dagent -> Zarafa
- A Zarafa user is able to reach an Exchange user, because the spooler connects to Exchange. Path:
Zarafa -> Spooler -> Exchange
- A Zarafa user is able to reach another Zarafa user. Path:
Zarafa -> Spooler -> Exchange -> Forward to Zarafa -> Postfix -> Dagent -> Zarafa
So from the above cases we can make the following two conclusions:
- Every user is able to email every other user.
- Postfix on the Zarafa server is ONLY being used for incoming mail traffic.
Explaining Spooler Config
Postfix on the Zarafa server is aware of the mail domain example.com and will consider every mail to *@example.com to be a local address. This is a very small example main.cf for postfix:
virtual_transport = lmtp:127.0.0.1:2003 virtual_mailbox_domains = example.com myhostname = mail1 mydestination = localhost mynetworks = 127.0.0.0/8, 192.168.0.0/16
This postfix config will realize that all mail send to *@example.com will be delivered to the Dagent over LMTP on port 2003. So if we would have connected the Spooler to connect to Postfix (and not exchange) we would NEVER be able to reach the users on the Exchange server. If we would then send an email from a Zarafa user to an Exchange user the following will happen:
Zarafa -> Spooler -> Postfix -> Dagent -> CANNOT FIND USER -> Bounce
This is why we connect the Spooler directly to Exchange. As already shown, the path will finally reach the Exchange user:
Zarafa -> Spooler -> Exchange
Out of Office from Zarafa Users
Zarafa has the option for it's users to set the Out of Office (OOO) Assistant. When this is set an email will be sent out to the sender of the email that the user is out of the office. The functionality is quite the same as any other Out of Office system on any other platform.
However: Zarafa uses a shell script to send out the OOO message. You can find the script in: /usr/bin/zarafa-autorespond
In the script you can see that the "sendmail" unix command is being used to send out the OOO message. The downside of this architecture is the fact that sendmail simply just drops the message in the Postfix queue. Now we could set a relayhost in the Postfix config, and let postfix use the Exchange server as a relay host. In the postfix main.cf add:
relayhost = 192.168.0.1
This will work fine when a user outside of the office will send an email to a Zarafa user.
In the following cases we assume that user_451 (on Zarafa) sets it's Out of Office Assistant:
Email from outside office
A user from outside the company (email@example.com) will send an email to the Zarafa user "user_451" (firstname.lastname@example.org). The following will happen:
Internet -> Exchange -> Forward to Zarafa -> Postfix -> Dagent -> DETECT OOO
As we can see the Dagent detects an OOO, so it will use the shell script to generate an OOO message and send that to "email@example.com":
zarafa-autorespond script -> Postfix (uses Exchange as RelayHost) -> Exchange -> Internet (deliver to firstname.lastname@example.org)
Email from another Zarafa user
Another Zarafa user "user_500" will now send an email to the Zarafa user "user_451" (remember that we have configured the spooler to connect to the Exchange server). The following will happen:
Zarafa -> Spooler -> Exchange -> Forward to Zarafa -> Postfix -> Dagent -> DETECT OOO
As we can see the Dagent detects an OOO, so it will use the shell script to generate an OOO message and send that back to the sender "user_500":
zarafa-autorespond script -> Postfix (sees that user_500 has example.com as mail domain, so will threat that as local mail) -> Dagent -> Zarafa (OOO delivered to user_500)
In this case you see that "user_500" has example.com as a mail domain. Postfix sees example.com as a local domain so it will try to deliver the message locally. In this case correct because "user_500" is a Zarafa POC user and so the OOO message needs to be delivered to Zarafa.
Email from an Exchange user
The Exchange user "user_1" will now send an email to the Zarafa user "user_451":
Exchange -> Forward to Zarafa -> Postfix -> Postfix -> Dagent -> DETECT OOO
As we can see the Dagent detects an OOO, so it will use the shell script to generate an OOO message and send that back to the sender "user_1" (remember that user_1 also has example.com as mail domain):
zarafa-autorespond script -> Postfix (sees that user_1 has example.com as mail domain, so will threat that as local mail) -> Dagent -> CANNOT FIND USER -> Bounce
In this case we see that the OOO message gets bounced. This is quite logical because postfix sees example.com as a local domain, so it will deliver the OOO message to the Dagent. The Dagent tries to deliver the OOO message to "user_1", BUT user_1 is NOT a POC user, and therefor does not have a mailstore on the Zarafa system.
You should decide for yourself if this is an acceptable situation for your POC or not. If you do find this an acceptable situation you do not have to keep reading, if you want a solution please read on.
Fixing OOO from Zarafa to Exchange
To sum up the above mentioned cases:
- OOO from Zarafa user to a user outside the office: OK
- OOO from Zarafa user to Zarafa user: OK
- OOO from Zarafa user to Exchange user: NOT OK
So the only case we need to fix is the last case in the list. The solution is achieved through different ways:
- Adding an extra postfix instance, so that:
- The first instance is the null client and will email ALL emails through the Exchange server as a relayhost.
- The second instance runs on the LAN IP address, and is aware of the mail domain example.com and will deliver to the dagent for that domain.
- Changing the way that Zarafa sends out OOO messages
You can choose yourself which solution you want for this, but I will only explain the last solution as this is the most simple to configure. In the last solution we let the dagent send out OOO message over MAPI, which means the spooler will finally send out the OOO message.
First get the script and place it on your Zarafa server. In this example we place the script in: /usr/bin/zarafa-ooo-mapi.py
- The script requires you to install the python bindings for Zarafa. Packages for this are shipped with every Zarafa > 6.40 release.
This is the code:
#!/usr/bin/python -u # from MAPI import * from MAPI.Struct import * from MAPI.Util import * from MAPI.Time import * import inetmapi import locale import sys import string import time # Set to False if you want a copy in the "Sent Items" folder DELETE_AFTER_SUBMIT=True # Get Username so we can login to the users' store USER=sys.argv # Read the RFC message we get from /usr/bin/zarafa-autorespond RFC = sys.stdin.readlines() RFC = ''.join(RFC) locale.setlocale(locale.LC_ALL, '') # Open MAPI session, we need to login through Unix socket for admin session session = OpenECSession(USER, "", 'file:///var/run/zarafa', flags = 0) # Open the users' default store store = GetDefaultStore(session) # Get Outbox EID and create message outboxeid = store.GetProps([PR_IPM_OUTBOX_ENTRYID], 0).Value sentid = store.GetProps([PR_IPM_SENTMAIL_ENTRYID], 0).Value outbox = store.OpenEntry(outboxeid, None, MAPI_MODIFY) message = outbox.CreateMessage(None, 0) # Open addressbook ab = session.OpenAddressBook(0, None, 0) # Convert RFC message to MAPI properties dopt = inetmapi.delivery_options() inetmapi.IMToMAPI(session, store, ab, message, str(RFC), dopt) # Set property for PR_DELETE_AFTER_SUBMIT message.SetProps([SPropValue(PR_DELETE_AFTER_SUBMIT, DELETE_AFTER_SUBMIT)]) message.SetProps([SPropValue(PR_SENTMAIL_ENTRYID, sentid)]) message.SetProps([SPropValue(PR_MESSAGE_CLASS, 'IPM.Note')]) # Submit the message message.SubmitMessage(0)
Set the execute bit on the script:
chmod 755 /usr/bin/zarafa-ooo-mapi.py
Now we need to change the autorespond config, so the dagent will invoke the new script. In /etc/zarafa/autorepond change the following values to:
The script will login to the store of the user, the script does not have a password of the user, so the script needs to be able to open an admin session within zarafa. Therefore the script needs to connect to the unix socket, and the script needs to be started as an admin user.
Currently the script is not able to connect with SSL certificates to Zarafa, so the script will only work when you have all the components (dagent, zarafa and the new script) running on the same server.
Copy of OOO message in Sent Items
The script has a config option which enables you to let script save a copy of the OOO message in the users "Sent Items" folder. This is probably unnecessary, but it was very easy to implement.
To enable this, check the DELETE_AFTER_SUBMIT option at the top of the script and set it to: