How to automatically mark email as invalid after campaign sent


My boss needs the contact email adress or prospect/account, to be checked as invalid after the sending of the campaign’s emails ( when an email doesn’t reach the contact email adress ) so I need to know where to code that, and how to code that.

I know i’m not the first to be in need if this functionnality.

It’s kind of urgent.


I think that you can achieve it with a workflow (which doesn’t require coding).

I have never done it but I don’t see why it shouldn’t be possible.

Hi, thanks for answering.

I checked in the workflow module and it is not possible.

However I found in the campaign module the file “ProcessBouncedEmails.php” with function markEmailAddressInvalid($email_address)

But this function is never called, do you know where I can get the response that the email is not valid in sugar so I can call this function ??

You can try with a custom scheduler.
The drawback would be that between one run and the other of the scheduler invalid emails will not be marked as invalid until the scheduler run. In any case you can run this scheduler quite often because it shouldn’t be a long query to perform and, unless you are constantly sending emails to the same lists, it will be unlikely that an invalid email will be picked for sending.

Have a look here:
There is a good example of a scheduler.


we actually use sendgrid to manage our emails, and I saw that sendgrid has an api to get the returns of the emails ( open, invalid etc…) I now have to find how to implement this api and get the json datas to deal with my problem, I’ll use the sugarcrm function to do this.


Hi again, thanks for helping me out !

I still have an issue, when I try to create my own job like described in suitecrmfordevelopers ( with the same example page 70 ) and then repair, I don’t see my new task in the scheduler page.

I also had to create the folders in custom (custom/Extension/modules/[strong]Schedulers/Ext/ScheduledTasks[/strong] ) because they didn’t exist in my project, is it normal ?

How can I indeed see my custom task ??

Thanks :dry:

You have to share more preciisely what you have done.

Saying that you have followed page 70 of the book is not sufficient. There may be something that is not working for some reason.

Actually, I thought that I could see my task directly when accessing the scheduler’page, but I saw my task in the task list when creating one.

But I was wondering if it is appropriate to do a custom scheduled task to manage my need, I actually need an action to happen whenever I send an email.

More presicely about my tools now, I will use 2 SendGrid GET API’s to get Jsons with the invalid and bounced emails and with these emails I will set the “invalid” column in the email table to 1, so that the invalid chechbox next to the person’s email can be checked.

But we won’t send emails all the time, so is the scheduler a good solution or is there another solution easier ?

Thanks for caring!

I have never done it myself but I believe that you can create a custom entry point that is called directly by your external script.
It’s something like a webtolead form which calls from an external application an entry point that updates some data in the CRM.

I did a quick search and found this article which may be a good starting point:

Additionnally you can always refer to the sugarcrm CE 6.5 manual

You can also check how webtolead forms work.

1 Like


I finally did it through a custom scheduled task, and used the native campaign fucntion to mark the emails as invalid in the database


If possible, please share your solution in the Forum so that, if someone has the same requirement in the future, he can also benefit from your findings.

Here’s my code as a custom scheduled task :


$job_strings[] = 'MarkBouncesEmails';

function MarkBouncesEmails()

    $API_KEY = 'MY API KEY';

    $ch1 = curl_init('');
    $ch2 = curl_init('');

    curl_setopt($ch1, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'authorization: Bearer '.$API_KEY));
    curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($ch2, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'authorization: Bearer '.$API_KEY));
    curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);

    $bounces = curl_exec($ch1);
    $invalid = curl_exec($ch2);


    $array = json_encode(array_merge(json_decode($bounces, true), json_decode($invalid, true)));
    $arr = json_decode($array, true);

    foreach ($arr as $data) {