Results 1 to 9 of 9

Thread: Thinking about Campaigns / Bounce handling

  1. #1
    Gyro.Gearless is offline Senior Member
    Join Date
    Apr 2009
    Posts
    47

    Default Thinking about Campaigns / Bounce handling

    Hi folks,

    it's late evening here, and i spent most of my day setting up the Campaigns module. OK, EMails are sent out,
    but i wonder if anyone out there is seriously using the bounce-handling feature?

    My current state is that bounced emails are ignored, and after revisting the relevant code @ modules/Campaigns/ProcessBouncedEMails.php some questions crop up:

    ProcessBouncedEMails.php as in 5.2.0j relies on the "remove me" link present in the body of the returned message - however, bounced emails from our local provider DO NOT contain the body of the original message, but only a short machine generated notice plus the original HEADER of the message

    So IMO this cannot work at all, or is at least highly dependent on a particular setup of the EMail transport system. Wouldn't it make much more sense to send the information needed for proper bounce handling along with the HEADER of the messages?
    All in all, the text matching done in ProcessBouncedEMails.php seems highly fragile code, to be polite...

    Related question: do people use this feature at all? Perhaps it's cheaper (in terms of time and money) to just ignore bounced emails...

    As always, your opinions are welcome!

    Cheers
    Gyro

  2. #2
    pema67 is offline Member
    Join Date
    Oct 2009
    Posts
    5

    Default Re: Thinking about Campaigns / Bounce handling

    Hi all,

    I was trying to do the same today, and came to the same conclusion.

    After searching the forums, it sounds like Sugar really needs the unique ID code included in the tracker in the body of the message. My mail server only includes header information for a bounced email, therefore Sugar can not assign the bounced email to the original target.

    If anybody has a workaround, let me (us) know.

    Peter

  3. #3
    hkphooey is offline Sugar Community Member
    Join Date
    Jan 2007
    Posts
    94

    Default Re: Thinking about Campaigns / Bounce handling

    I have to say I'm a little disappointed here as well, so I think this is worth pursuing in a thread. The last time I set up SugarCRM, bounce handling did seem to be working in there. It wasn't perfect by any means, but it did at least try.

    As I remember it, a previous version of SugarCRM used to check the bounce mailbox and bring all the mails into SugarCRM. Once they're in the database, it could then search through them: It would run through them and try to look for the various bounce messages. If it detected a bounce message it would then try to extract the email from the message, and if it did, then it would mark the message as bounced. (Is this how it used to be, or am I completely delusional?)

    This wasn't perfect. In fact it was pretty bad because of the huge variety of different Mail bounce messages. I can see why the developers weren't happy with it. However, they've now replaced it with something which does this.

    Checks the bounce mailbox. Looks for something which isn't there and then ... Nothing.

    So how can we solve this. I personally want to be able to mark bounces as bad emails. I want to know when a contact is bad so I can update it. I want to know if someone has left a company. If a whole domain goes bad I want to know about it - it says something about the company which is running the domain. Its valuable business intelligence.

    OK well if SugarCRM won't do this for us, how can we get the information. If we have access to the mail server logs then we can probably mine those. I'll be doing that in the next few days and will post my methods here, for people to use and improve on. I'm currently running postfix, but we should figure this out for sendmail as well, and for Exchange.

    But then what if people don't have access to the mail logs? How can we extract the info from the emails?

  4. #4
    roblaus's Avatar
    roblaus is offline Sugar Community Member
    Join Date
    Dec 2006
    Location
    Vienna / Austria
    Posts
    2,850

    Default Re: Thinking about Campaigns / Bounce handling

    I couldn't agree more to what was said here and in so many other threads. But let's keep it simple:

    Bounces can't be interpreted properly - ok so be it. But we can.

    It just lacks a small tool which displays bounced messages (they are already in a folder...) plus the first 10-20 header lines. A checkbox next to it should then, after some confirmation of the list, trigger the update of the contact/lead. This won't work for 100,000s of emails but then Sugar is the wrong tool anyway.

    I am not a programmer but somebody may pick up the idea...
    __________________________
    Robert Laussegger
    http://www.iscongroup.net

    Bei Fragen: support@iscon.at
    Die deutschen Sprachdateien für SugarCRM und das deutsche Handbuch gibt es hier: http://goo.gl/kPsAz
    Ab sofort auch mit 6.4.2

  5. #5
    hkphooey is offline Sugar Community Member
    Join Date
    Jan 2007
    Posts
    94

    Default Re: Thinking about Campaigns / Bounce handling

    OK, so I had some spare time to play with this and this is what I came up with. This is only useful if you have access to your own logfiles, and if you're running postfix mail server on Linux.

    Its ugly, clumsy and kludged, but it's working for me. I'm hoping that others can hack this around to make it work on other platforms. And I'm sure someone can improve on my code. I'll make a wiki-page with the fruits of this thread.

    This script generates a report log and optionally an SQL script to remove offending emails. Note that you might not necessarily want to remove all the emails, so you need to review the report first. If you're gung ho, I guess you could automate the script, but I certainly wouldn't advise it.

    Code:
    #!/bin/bash
    # SugarCRM logfile Bounce parser v. 1.1
    
    OUTPUTFILE=bad_emails_`date +%F`.txt
    OUTPUTSQL=bad_emails_`date +%F`.sql
    MAILLOG=mail.log
    
    function text_report {
    echo "Starting to Analyse logs at `date`" > $OUTPUTFILE 
    echo "Start Date = " `head -1 $MAILLOG | awk '{ print $1, $2, $3 }'`  >> $OUTPUTFILE
    echo "End Date = " `tail -1 $MAILLOG | awk '{ print $1, $2, $3 }'` >> $OUTPUTFILE
    echo "Crunching " `wc -l $MAILLOG | awk '{ print $1 }'` " lines" >> $OUTPUTFILE
    echo  >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    echo  >> $OUTPUTFILE
    echo "======= Host not found ========" >> $OUTPUTFILE
    
    echo  >> $OUTPUTFILE
    echo "=> Domains associated with Host Not found" >> $OUTPUTFILE
    grep "Host not found" $MAILLOG | sed -e 's/.*for name=//' | sed -e 's/ type=.*//' | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    echo  >> $OUTPUTFILE
    echo "=> Email addresses associated with Host Not found" >> $OUTPUTFILE
    grep "Host not found" $MAILLOG | sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    
    echo  >> $OUTPUTFILE
    echo "========= Connection Refused ===========" >> $OUTPUTFILE
    
    echo  >> $OUTPUTFILE
    echo "==> Domains with 'Connection Refused'" >> $OUTPUTFILE
    grep "Connection refused" $MAILLOG | sed -e 's/.*connect to //' | sed -e 's/ Connection refused.*//' | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    echo  >> $OUTPUTFILE
    echo "==> Emails associated with 'Connection Refused'" >> $OUTPUTFILE
    grep "Connection refused" $MAILLOG |  sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | grep -v "Connection refused" | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    echo >> $OUTPUTFILE
    echo "====== Connection Timed Out ======== " >> $OUTPUTFILE
    
    echo >> $OUTPUTFILE
    echo "==> Domains with Connection Timed Out" >> $OUTPUTFILE
    grep "Connection timed out" $MAILLOG | sed -e 's/.*connect to //' | sed -e 's/ Connection timed out.*//' | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    echo >> $OUTPUTFILE
    echo "==> Emails associated with Connection Timed Out" >> $OUTPUTFILE
    grep "Connection timed out" $MAILLOG | sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | grep -v "Connection timed out" | sort | uniq -c >> $OUTPUTFILE
    echo "==================" >> $OUTPUTFILE
    
    echo "Your report has been generated in " $OUTPUTFILE
    echo 
    }
    
    function sql_init {
    	echo "-- Initialising file - " `date` > $OUTPUTSQL
    }
    
    function sql_emails {
    
    echo "-- Emails for Host not found" >> $OUTPUTSQL
    for email in `grep "Host not found" $MAILLOG | sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | sort -u`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address = "'$email'";' >> $OUTPUTSQL
    done
    
    echo "-- Emails for Connection Refused" >> $OUTPUTSQL
    for email in `grep "Connection refused" $MAILLOG |  sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | grep -v "Connection refused" | sort -u`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address = "'$email'";' >> $OUTPUTSQL
    done
    
    echo "-- Emails for Connection Timed Out" >> $OUTPUTSQL
    for email in `grep "Connection timed out" $MAILLOG | sed -e 's/.*to=<//' | sed -e 's/>, relay=none.*//' | grep -v "Connection timed out" | sort -u`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address = "'$email'";' >> $OUTPUTSQL
    done
    }
    
    function sql_domains {
    
    # NOT ACTIVE YET
    echo "-- Domains for Host not found" >> $OUTPUTSQL
    for domain in `xxx`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address LIKE "%'$domain'";' >> $OUTPUTSQL
    done
    
    echo "-- Domains for Connection Refused" >> $OUTPUTSQL
    for domain in `xxx`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address LIKE "%'$domain'";' >> $OUTPUTSQL
    done
    
    echo "-- Domains for Connection Timed Out" >> $OUTPUTSQL
    for domain in `xxx`
    do
      echo 'UPDATE email_addresses set invalid_email=0, date_modified=now() WHERE email_address LIKE "%'$domain'";' >> $OUTPUTSQL
    done
    }
    
    function sql_end {
    	echo "SQL report generated to $OUTPUTSQL."
    }
    
    # Main control structure
    
    echo "----------------------------------------------------------"
    echo "Analysing $MAILLOG and outputting to $OUTPUTFILE and/or $OUTPUTSQL"
    echo "Log Start Date = " `head -1 $MAILLOG | awk '{ print $1, $2, $3 }'`
    echo "Log End Date = " `tail -1 $MAILLOG | awk '{ print $1, $2, $3 }'`
    echo "Crunching " `wc -l $MAILLOG | awk '{ print $1 }'` " lines" 
    echo "----------------------------------------------------------"
    echo Choose an option
    echo 
    echo " 1) Run Text Report only"
    echo " 2) Run Text Report and generate SQL code"
    echo " 3) Generate SQL code only"
    
    read CONN
    
    case $CONN in
    	"1") 	text_report;;
    	"2") 	text_report
    		sql_init
    		sql_emails
    		sql_end;;
    	"3") 	sql_init
    		sql_emails
    		sql_end;;
    	*) echo "Sorry, try again";;
    esac
    And yes, a neat web interface would be much, much better!
    Last edited by hkphooey; 2009-11-17 at 07:15 AM. Reason: Updated code

  6. #6
    hkphooey is offline Sugar Community Member
    Join Date
    Jan 2007
    Posts
    94

    Default Re: Thinking about Campaigns / Bounce handling

    Ok, everyone's gone quiet again. I've updated the code in the previous post, for those of you with access to their postfix maillogs.

    However I know this doesn't fit most people. I've now tried another approach which takes bounces in unix mailbox/mbox format and processes them. If your bounces come back to a sendmail or postfix mailbox, or if you download them to Thunderbird, or Evolution, or ... any other email client which uses this format, then you can use this. Outlook and Exchange users are out of luck. To run the script you'll need access to a Linux box, but in these days of VirtualBox, this isn't too tricky to get.

    OK the script. mailbox_parse.sh
    Code:
    #!/bin/bash
    
    ################ exclude emails from the originating domain ##########
    EXCLUDEDOMAIN="example.com"
    ## Name of files to output. 
    OUTPUTTEXT=bad_emails_`date +%F`.txt
    OUTPUTSQL=bad_emails_`date +%F`.sql
    
    
    ######################################################################
    
    function print_help {
    	echo "  Usage:"
    	echo "    $0 -f /path/to/infile [-sql]" 
    	echo "    Parameters:"
    	echo "    -f              Specify filename of mailbox file"
    	echo "    -s              Additional generation of sql query text to file"
    	echo "    -h | --help     This usage information"
    }
    
    function text_report {
    	# First run through the input file looking for the 550 code and print out 1 line before and 2 lines after.
    	grep -A 1 -B 2 "550" $PARSEFILE | \
    	# Remove all carriage returns and replace with a space
    	 tr "\n" " " | \
    	# Collapse all multiple spaces into a single space
    	 tr -s " " | \
    	# Now replace the -- marks that grep put in with a new line. Each entry is now on a single line
    	 sed 's/--/\n/g' | \
    	# Now read in grepmail.txt and match every line in it against the remaining lines. 
    	# grepmail.txt is a plain text file with a common email server rejection phrase on each line.
    	 grep -f grepmail.txt | \
    	# Now from the remaining lines, pull out the email address strings.
    	 grep -o "[[:alnum:][:graph:]]*@[[:alnum:][:graph:]]*" | \
    	# The last operation left a lot of crud on the ends of the email addresses, so we need to clean them up
    	# Remove html paras and breaks and '550-' left on by some mailservers
    	 sed 's/<p>\|<br>\|550-//g' | \
    	# Remove lots of punctuation < > : ; ... ( ) 
    	 sed 's/<\|>\|:\|;\|\.\.\.\|(\|)//g' | \
    	# Remove single quote (needs to use -e so needs separate sed command)
    	 sed -e s/\'//g | \
    	# Take out lines containing ##rfc822 as the email addresses are malformed.
    	 grep -v "##rfc822" > $OUTPUTTEXT
    
    	###### Now go in again for DSNs, which don't have 550 in them. 
    	grep -A 5 "This is an automatically generated Delivery Status Notification" $PARSEFILE | grep -o "[[:alnum:][:graph:]]*@[[:alnum:][:graph:]]*" >> $OUTPUTTEXT
    	
    	##### Now deal with Lotus Domino ... oh.
    	grep -A 1 "Diagnostic-Code: X-Notes;" $PARSEFILE | sed -e 's/ //g' | tr -d "\n" | sed 's/--/\n/g' | sed 's/.*(//g' | sed 's/).*//g' >> $OUTPUTTEXT
    	
    	### Now MS Exchange
    	grep -A 2 "Delivery has failed to these recipients or distribution lists" $PARSEFILE | grep -o "[[:alnum:][:graph:]]*@[[:alnum:][:graph:]]*" | sed 's/.*mailto://g' | sed 's/>//g'  >> $OUTPUTTEXT
    
    	## Now Take out lines containing the sending domain, sort file and remove duplicates
    	 grep -v $EXCLUDEDOMAIN $OUTPUTTEXT | sort -u  -o $OUTPUTTEXT
    
    	echo "... Text written to $OUTPUTTEXT"
    }
    
    function sql_report {
    	echo "UPDATE email_addresses SET invalid_email = 1, date_modified=now() WHERE email_address IN (" > $OUTPUTSQL
    
    	# Put quotes at the beginning of each line, quotes and commas at the end, except the last line.	
    	sed "s/^/'/g" $OUTPUTTEXT | sed "s/$/',/g" | sed '$s/,$//' >> $OUTPUTSQL
    
    	echo ");" >> $OUTPUTSQL
    	echo "... SQL written to $OUTPUTSQL"
    }
    
    #################### Process Command line ####################
    
    while [ "$1" != "" ]; do
        case $1 in
            -f )           	shift
                                    PARSEFILE=$1
                                    ;;
            -s )    	shift
    				SQLREPORT=yes
                                    ;;
            -h | --help )           print_help
                                    exit
                                    ;;
            * )                     print_help
                                    exit
    				;;
        esac
        shift
    done
    
    
    if [ -e "$PARSEFILE" ]
    then
    	echo " ... Processing $PARSEFILE"
    else
    	echo "No input file specified, or file doesn't exist"
    	echo 
    	print_help
    	exit
    fi
    
    
    echo 
    
    text_report
    
    if [ "$SQLREPORT" = "yes" ]; then
    		sql_report
    fi
    In the same directory as the script you'll need a file called grepmail.txt with the vital lines of error messages to include. Mine looks like this, which seems to catch most of them. Lines can be added/subtracted to suit.

    Code:
    User unknown
    No such user
    not a valid mailbox
    no such recipient
    RecipNotFound
    Address rejected
    Mailbox unavailable
    Recipient address rejected
    not allowed
    Invalid recipient
    Run it without any parameters to get the syntax, but basically it needs an mbox file as an input, and optionally a -s flag to generate the sql query for removing them from your database.

    That's about it. It pulled out 550 email addresses from 1000 odd bounces, so I think its working pretty well. UPDATE ... added some more lines to take out messages bounced from Exchange and Domino, and changed the structure of the script a little ... now it gets 740 bounces out of 1000 emails.
    Last edited by hkphooey; 2009-11-19 at 12:26 AM.

  7. #7
    pema67 is offline Member
    Join Date
    Oct 2009
    Posts
    5

    Default Re: Thinking about Campaigns / Bounce handling

    Okay, I got a partial result. Now the Status report of the Campaign shows me the bounced emails.

    To get this to work, I had to activate 'Save raw Source' in 'Admin - Inbound Email'. In addition, I had to do a small modification in 'ProcessBouncedEmails.php' in the modules/Campaigns folder:

    // mod. PM: raw_source includes attachment as well, description contains only the body
    // $email_description = $email->description;
    $email_description = $email->raw_source;
    // end mod.

    Last, but not least, you need a SMTP server which returns the originally sent email either in the message body or as an attachment.

    As I said, bounced emails are now displayed as such in the Campaign Status Report. What does not happen is the update of the target email as invalid.

    Continue my research.

    As always, I am thankful for some hints...

    Peter

  8. #8
    parsec is offline Senior Member
    Join Date
    Sep 2009
    Posts
    26

    Default Re: Thinking about Campaigns / Bounce handling

    I recognize the problem. I did not take the time to implement a solution due to the fact I have different problems to serve first.

    In the past I used a script called phplist (http://www.phplist.com/). This script has proper bounce handling if I recall well. So maybe someone can port the bouncehandling from that script to SugarCRM....

  9. #9
    dch
    dch is offline Junior Member
    Join Date
    Feb 2010
    Posts
    6

    Red face Re: Thinking about Campaigns / Bounce handling

    [QUOTE=pema67;192691]

    In addition, I had to do a small modification in 'ProcessBouncedEmails.php' in the modules/Campaigns folder:




    Hi..

    Could you please explain this in more detail?.. For a lay-man like my self... How do i do this?

    Many thanks

    Dan

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Bounce Handling on email campaigns
    By jamesj55 in forum General Discussion
    Replies: 1
    Last Post: 2009-09-05, 01:59 PM
  2. Problems with e-mail bounce handling
    By imn in forum Developer Help
    Replies: 0
    Last Post: 2009-06-17, 06:40 AM
  3. Replies: 0
    Last Post: 2007-05-21, 06:10 PM
  4. Bounce Handling & Tracker URLs
    By Beefeater in forum Help
    Replies: 3
    Last Post: 2007-03-07, 11:53 PM
  5. Replies: 0
    Last Post: 2007-02-13, 04:10 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •