Share your knowledge at the LQ Wiki.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


Search this Thread
Old 10-03-2010, 08:03 AM   #1
Registered: Jul 2008
Posts: 106

Rep: Reputation: 23
relaying SMTP-server using authentication on a remote server using IMAP

I was given the assignment to enable our outgoing SMTP-server to be used for SMTP-clients not within our subnet. This SMTP-server is already relaying for all our customers using their source IP as a credential. A normal ISP's outgoing SMTP-server.

SMTP using a login and password on port 587 is something Sendmail supports.

After some investigating I found out that SASL was the way to go. A SASL service needs to be installed and sendmail can be configured to use that. SASL itself can be configured to use LDAP and some other methods, but I chose for the method 'rimap' (remote IMAP).

SASL would then issue a login to an IMAP-server and login to it and if the IMAP-server would allow it then it would give the Mail Agent (sendmail) that same answer.

This was almost what I wanted. On our net we have several servers and there's no way to configure sasl to use more than 1 IMAP-server. That's why I wrote a little shell script which behaves as an IMAP-server and would then find out which server it had to go to. If that server turns out to be one of ours it would login using IMAP and ask it there.

It finds out the IP of the IMAP-server by doing some A-record lookups. It will try mail.<domain>, pop.<domain> and then <domain>. If this doesn't result into an IP within our subnet it will fail.

I used xinetd to listen to port 143.
Configuring sasl & sendmail is not within the scope of this thread, but if someone needs some help...

feedback and comments about security are appreciated.

cat /etc/xinetd.d/imap
service imap
  socket_type = stream
  server = /usr/local/sbin/imap
  only_from = localhost
  protocol = tcp
  user = root
  group = root
  wait = no
  disable = no
  log_on_success = HOST DURATION EXIT
  log_on_failure = HOST
# cat /usr/local/sbin/imap
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin


export TTL=3600
export SERVER=

CURSECONDS=`date +%s`
ISODAY=`date '+%Y%m%d'`
TABCHAR=`echo -e '\t'`


write_log () {
  [ ${LOGGING} = 0 ] || echo "`date '+%b %d %H:%M'` imapd $*" >>${LOGFILE}

login_success () {
  write_log "${CLIENT} OK LOGIN completed."
  echo "${CLIENT} OK LOGIN completed."
  exit 0
login_failed () {
  write_log "${CLIENT} NO Login failed."
  echo "${CLIENT} NO Login failed."
  exit 1

no_login () {
  write_log "${CLIENT} NO Login command."
  echo "${CLIENT} OK."
  exit 0

check_domain () {
  SERVER=`host -tA "$1." | grep -o 'has address .*' | awk '{print $3}'`
  [ -z "${SERVER}" ] && return 1
  [ -z "`which dig 2>/dev/null`" ] || TTL=`dig $1 | grep -A10 'ANSWER SECTION' | grep -B10 'AUTHORITY SECTION' | grep "IN${TABCHAR}A" | head -n1 | awk '{print $2}' | tr -cd '[0-9]'`
  [ -z ${TTL} ] && TTL=3600
  [ ${DEBUG} = 0 ] || write_log "Server found using domain $1.: ${SERVER} (${TTL})"
  return 0

if [ -z "`which nc 2>/dev/null`" ] ; then
  write_log "nc (netcat) is not installed."
  echo "imap NO netcat (nc) installed"
  exit 1

trap "" 2 3 24

echo "* OK IMAP4rev1" ; read -t 120

if [ "$REPLY" ]; then
  [ ${DEBUG} -gt 1 ] && write_log "RAW input: '`echo "${REPLY}" | tr -cd '[ -~]'`'"
  echo "${REPLY}" | grep -qi "LOGIN " || no_login

  CLIENT=`echo "${REPLY}"   | awk '{print $1}'`
  EMAIL=`echo "${REPLY}"    | awk '{print $3}' | tr -cd '[#-~]'`
  PASSWORD=`echo "${REPLY}" | awk '{print $4}' | tr -cd '[#-~]'`

  if ! echo "${EMAIL}" | grep -q '@' ; then
    write_log "Email: \"${EMAIL}\""

  PASSWORD64="`echo -n "${PASSWORD}" | base64`"
  [ ${DEBUG} -gt 1 ] && write_log "Email: \"${EMAIL}\" Password: \"${PASSWORD64}\""

  [ -f ${PASSFILE} ]        || touch ${PASSFILE}
  [ -f ${PASSFILE}.failed ] || touch ${PASSFILE}.failed
  PASSLINE="`grep "^${EMAIL}" ${PASSFILE}`"

  if [ ! -z "${PASSLINE}" ] ; then
    TIME=`echo "${PASSLINE}" | awk '{print $2}'`
    if [ ${CURSECONDS} -lt ${TIME} ] ; then
      PASSRESULT=`echo "${PASSLINE}" | awk '{print $3}'`
      if [ "${PASSRESULT}" == "${PASSWORD64}" ] ; then
        [ ${DEBUG} = 0 ] || write_log "Email: \"${EMAIL}\" authenticated from cache"

  # Check if someone authenticated today
  FAILLINE="`grep "^${ISODAY} ${EMAIL}" ${PASSFILE}.failed`"
  if [ ! -z "${FAILLINE}" ] ; then
    OCCURENCE=`echo "${FAILLINE}" | awk '{print $3}' | tr -cd '[0-9]'`
    if [ ${OCCURENCE} -gt ${FAILED_ALLOWED} ] ; then
      sleep 5
      # If someone has already succesfully authenticated, don't do a new lookup but just fail
      # It's already an exceptional situation which can in worst case take 24 hours
      if [ ! -z "${PASSLINE}" ] ; then
        OCCURENCE=$(( ${OCCURENCE} + 1 ))
        sed -i -e "s/^${ISODAY} ${EMAIL}.*/${ISODAY} ${EMAIL} ${OCCURENCE} ${PASSWORD}/" ${PASSFILE}.failed

  DOMAIN=`echo "${EMAIL}" | awk -F@ '{print $2}'`
  echo "${DOMAIN}" | grep -q '\.' || login_failed

  if ! check_domain "mail.${DOMAIN}"  ; then
    if ! check_domain "pop.${DOMAIN}"  ; then
      check_domain "${DOMAIN}"
  [ -z "${SERVER}" ] && login_failed

  # Only for our servers
  if ! echo "${SERVER}" | grep -q "89\.250\.1[789]" ; then
    write_log "Foreign address: \"${EMAIL}\" wanted to authenticate (${SERVER})"


  # if imaplogin ${SERVER} ${EMAIL} ${PASSWORD} >/dev/null ; then
  if echo -e "${CLIENT} LOGIN \"${EMAIL}\" \"${PASSWORD}\"" | nc -i2 ${SERVER} 143 | grep -q "${CLIENT} OK" ; then
    if grep -q "^${EMAIL}" ${PASSFILE} ; then
      sed -i -e "s/^${EMAIL}.*/${EMAIL} ${TIME_VALID} ${PASSWORD64} ${SERVER} ${REMOTE_HOST}/" ${PASSFILE}
    if grep "^${ISODAY} ${EMAIL}" ${PASSFILE}.failed ; then
      OCCURENCE=$(( ${OCCURENCE} + 1 ))
      sed -i -e "s/^${ISODAY} ${EMAIL}.*/${ISODAY} ${EMAIL} ${OCCURENCE} ${PASSWORD}/" ${PASSFILE}.failed
      echo "${ISODAY} ${EMAIL} 1 ${PASSWORD}" >>${PASSFILE}.failed

Last edited by frater; 10-07-2010 at 07:21 AM. Reason: update code: logging should not reveal passwords, especially for foreign servers
Old 10-03-2010, 08:23 AM   #2
Registered: Jun 2001
Location: UK
Distribution: Gentoo, RHEL, Fedora, Centos
Posts: 43,398

Rep: Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964Reputation: 1964
Why not just enable SMTP authentication?? This seems really strange and OTT from what I understand of your situation.
Old 10-04-2010, 01:55 AM   #3
Registered: Jul 2008
Posts: 106

Original Poster
Rep: Reputation: 23
Originally Posted by acid_kewpie View Post
Why not just enable SMTP authentication?? This seems really strange and OTT from what I understand of your situation.
I am using SMTP-authentication on Sendmail (should also work with Exim4 and Postfix).
It authenticates using Cyrus-SASL which is already builtin for sendmail.

sasl supports several methods and will pass the result to the MTA.
The method I'm using is rimap (remote IMAP) which already is being used (I can only assume).

What I wrote is a fake IMAP-server which enables me to authenticate to more than 1 IMAP-server.
It will take the realm of the email-address (the domain) and then authenticates to that server.

Last edited by frater; 10-04-2010 at 05:15 AM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Server configuration for small office server, which smtp, pop imap server and backup whitelinux Linux - Server 4 04-06-2010 11:26 AM
SMTP authentication error and server could not connected in postfix server Ravinder Singh Thakur Linux - Server 1 11-02-2009 10:22 AM
Exim4 won't let me send email relaying it to ISPs SMTP server spaceuser Linux - Server 2 09-19-2009 06:10 AM
Relaying mails through auth-SMTP server ? nileshgr Linux - Server 2 05-25-2008 11:14 PM
SMTP server responds: Relaying denied, proper authentication required SaRS AeOL Linux - Newbie 2 04-28-2008 04:52 PM

All times are GMT -5. The time now is 05:47 PM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration