Check if email was sent -- Delphi Indy10 - email

My app sends emails to the given addresses and this works fine. Problem is, that one of these email addresses could be incorrect and not exist. I am using Delphi 2009 and Indy10 components (TIdSMTP and TIdMessage).
Try
Try
SMTP.Connect;
SMTP.Send(MailMessage);
resultTmp := ?????
Except
on E : Exception do begin
ShowMessage(E.Message);
end;
End;
Finally
if SMTP.Connected then begin
SMTP.Disconnect;
end;
End
How can I check the if an email was sent or not ? On my test Gmail account I got emails like "Address not found" if I try to send email to incorrect address.
Thanks

When you send an email to an SMTP server, all you are really doing is given the email to the server, and it reports back whether it will TRY to deliver it to the specified recipient(s). There is no guarantee of delivery.
IF a given recipient is local to that server/domain, the receiving SMTP server can report immediately (in reply to the SMTP RCPT TO command) whether it will deliver the email to that recipient or not. TIdSMTP can report such errors to your code, via the TIdSMTP.OnFailedRecipient event, or by raising an exception.
However, IF the email cannot be delivered to a recipient immediately, it has to be delivered asynchronously, usually by being relayed to another server (potentially many times), and that delivery does not happen until after you have given the email to the initial server and moved on.
As such, errors that occur during that delivery cannot be reported by TIdSMTP. The SMTP server that fails to deliver the email (which may be the same server you connected to, or may be another server that the email was relayed to) will send an email back to the original sender's inbox explaining the error(s) that occurred.
So, to detect those kind of errors, you have to check your inbox periodically, such as with POP3 or IMAP, and then parse the emails for details. And such errors may take some time to arrive, depending on the nature of the error(s), how long a given server retries before giving up, etc. So, it may take minutes, hours, or even days to get a response back, if at all.
In general, there is no single reliable way to know if a given recipient is valid in a timely manner. You should just let SMTP do its work and handle errors asynchronously.
However, if you must verify, one way would be to use TIdDNSResolver to lookup the MX record(s) of a recipient's domain, then connect TIdSMTP to that domain server(s) and call TIdSMTP.Verify() to check if the recipient exists on those server(s). But this requires the server(s) to implement the SMTP VRFY command, which is optional by the SMTP protocol spec, and may not be be implemented by modern servers to avoid leaking knowledge, and plug vulnerability holes.

I'm not sure you can know if a adress exist, because in gmail you sent an email and google server answer you that it's didn't exist.
With Send method you can get error return by your server SMTP, like "adress not valid", "socket error", .. but nothing about the recipient.
The email you use to sent message will get a reply if recipient's SMTP detect an error.
In my code I use EIdSMTPReplyError too.
try
SMTP.Send(MailMessage);
except
on E : EIdSMTPReplyError do
begin
ShowMessage(E.ErrorCode.ToString + ' : ' + E.Message);
end;
on E : Exception do
begin
ShowMessage(E.Message);
end
end;

Related

Google MX telnet returns 250 OK for invalid email addresses

We are trying to figure out how to reduce the amount of bounces for our email platform and, one of the solutions we've found on the internet is to, via telnet, verify if the email exists.
So, for this example, we connect to the MX:
telnet alt4.aspmx.l.google.com 25
We start the communication:
helo hi
And, for every email we try (valid and invalid ones), we always receive the same response:
mail from: <fsafsaffsf#FasgagaoaSFasfas.co>
250 2.1.0 OK d8si998940wrc.143 - gsmtp
Are they doing this to prevent maybe a possible listing of valid emails?
What is the best way to verify if an email is valid before sending an email to it? We need this because our clients often uploads a spreadsheet with customer emails and always one or two of them are mistyped.
Thanks.
For a given recipient email address, you can:
extract its domain name (everything after #)
query DNS for the MX record(s) of that domain
for each specified server, connect and issue a VRFY command (see RFC 5321 Section 3.5), asking the server to verify the email address.
stop when you get a success reply.
However, SMTP servers are not required to implement VRFY. The simpler solution would be to just send the email normally, and then handle any errors from the RCPT TO command, and also handle the possibility that you simply can't always detect delivery errors in real time. If the email has to be relayed across servers, it might not fail on the server you use for sending, it may not fail until it is relayed to another server after you have already ended your SMTP session. In which case, the only way to detect delivery errors is to monitor your inbound mailbox for delivery failure emails being sent back to you.

How to check if Siebel has successfully delivered an email?

We send a lot of email messages from our Siebel 7.8 application, and we'd like to determine whether they have been successfully delivered or not.
According to the Bookshelf, if the SMTP server is down, the Communications Outbound Manager retries to send the message later, so that's not a problem. However, there are still plenty of issues which could cause an email to not be delivered, such as a typo in the address, the receiver having reached its storage quota, etc.
We send our messages this way:
var ps = TheApplication().NewPropertySet();
ps.SetProperty("ActivityId", outboundEmailActivityId);
ps.SetProperty("CommProfile", commProfile);
ps.SetProperty("ProcessMode", "Local");
var bs = TheApplication().GetService("Outbound Communications Manager");
bs.InvokeMethod("SendMessage", ps, psOut);
Using ProcessMode = Local allows us to detect a few errors. For example, if we try to send a message to a non-existant account in the same domain of our SMTP server, it returns 550 Unknown user and then 503 Must have sender and recipient first. The Outbound Communications Manager raises an exception, and we capture and handle it.
However, if we send a message to a non-existant account in a different domain, our SMTP server can't know that it will fail, and therefore it returns 250 Queued, and our code completes successfully. Later (it can range from seconds to a few hours later), we will receive a "Message undeliverable" error message, but at this point we only know that an outbound message failed, we don't know which one.
Is there any way in which Siebel can handle these 'Message undeliverable' notifications automatically?
We are thinking of writing our own process for that, but it seems like a huge task: we'd have to parse the delivery failure notification, identify the failing recipient, search for all the recent messages sent to that address, and somehow, guess which one failed (based on the Message-Id if we are lucky and can read it within Siebel, or on the Subject otherwise).
The problem is that SMTP is by its nature neither a synchronous nor reliable protocol (i.e. in the sense of "engineered for guaranteed delivery"). Your Siebel app server will connect to its assigned SMTP server and ask it to accept a message for delivery and at that time there are a few high level validations that can be perform (some of which you've mentioned but which can also include policy enforcement such as checking whether your (possibly anonymous) identity is authorized for relaying messages to external domains). Once that conversation ends, there is not much else you can reliably do because again, everything from that point is asynchronous and not guaranteed for delivery (any number of intermediate relay agents can be involved, each with their own potential for outages with or without retry, each with the ability to honor or ignore requests for delivery or read receipts or to report invalid recipients, throwing your message in a junk folder or not, etc.). Certainly you can attempt to work with any bounce notifications you do happen to get to try to correlate them back to the sender but that would be outside the context of your sending code.

The error that the other server returned was: 550 Mailbox does not exist

The problem started suddenly. I have a problem that I can not solve when a random address send email to my domain martizi.com:
Technical details of permanent failure: Google tried to deliver your
message, but it was rejected by the server for the recipient domain
martizi.com by feedback-smtp.us-west-2.amazonses.com.
The error that the other server returned was: 550 Mailbox does not
exist!"
I use SES only to send email, just that. I want to be clear about the problem I'm having:
Use SES only to send email.
I have a corporate email that is provided by another company (here I can not receive the emails)
In my domain I have another MX address that is from the company email. Sometimes when someone tries to send email to some box # martizi.com, it returns with the error shown above.
I've seen a solution to this problem: Adding email from domains
SES panel> Domains> Mail From Domains> ...
After this he gives me an mx record to put in my domain, I put it, however it stays PENDING VERIFY and after 72 hours, it fails. I've done this twice and it does not check. Is this the solution?
TKS!
Either you are receiving email for martizi.com using SES, or you aren't.
You say that you aren't. This means you should not have this entry in DNS.
martizi.com. 3600 IN MX 10 feedback-smtp.us-west-2.amazonses.com.
With that entry, you're telling the world that feedback-smtp.us-west-2.amazonses.com. is one possible server (of several) that will accept incoming email addressed to martizi.com. That isn't the case, so the existence of this is a misconfiguration. Remove this entry.

How to make sure that the email was sent in yii2?

In my project when the user stored a new record to database, sent to him email with to perform afterSave() Method.
How to make sure that the email was sent?
I don't think this is something to do with yii2 or the afterSave() event (as long as the afterSave event is triggered, which you can verify by Runtime Logging for example). When using PHPMailer class you can see this discussion about making sure an email has been sent.
$mail->send() will not always return true. It returns true if the part of the sending process it was involved with works. So if you send to an unknown address, but do so via gmail, gmail's servers don't know whether the address exists or not at the time, so it will be accepted and bounced later. If you were sending to a gmail address when sending through gmail, then it would fail immediately.
If an account does not exist at all, most servers (including gmail) will still give a 5.1.1 "Unknown user" response, and that will be reported correctly by PHPMailer if you send by SMTP directly to the recipient's supposed mail server (but not if you send via an intermediate server (like gmail) or using mail()). PHPMailer doesn't have built-in support for doing that, but doing it yourself only involves a call to getmxrr and setting Host manually. Also you won't need to use authentication if you send that way.
You can do various things like check if a domain exists at all - if it doesn't, mail delivery won't work. Some servers will accept all addresses and send bounces later (e.g. if they have a spam filter with a long processing queue), but if you get rejected up-front, it's a pretty sure indication that the address doesn't exist.
You need to look into bounce handling too which will allow you to remove addresses that looked ok but later proved not to be, which is an entirely separate thing from anything that PHPMailer does. I will warn you now - bounce handling is extremely unpleasant!
You should also send using tls on port 587, not ssl on 465; see the gmail example provided with PHPMailer.
I would also recommend you to send mails via an SMTP auth connection trough PHPMailer.

Deleting email addresses where email wasn't sent

I personally can't see a way to do this, but I'm hoping there could be a clever hack to make it work.
We have to send out regular emails to customers, many of who's emails expire and give us a mail delivery failure. To keep the database accurate and clean, I'd like to delete their record from the database when an email fails to be sent to them.
So currently it goes a little something like this:
<cfloop query="rsCustomers">
<cftry>
<cfmail to="rsCustomers.Email" from="us#ourcompany.com" failto="fails#ourcompany.com" subject="Whatever">
[email text here]
</cfmail>
<cfcatch type="any">
<!--- just to skip this record when it fails to send --->
</cfcatch>
</cftry>
</cfloop>
I could run a query within the catch area to delete records when there was an error in the record (e.g. malformed email address). But nothing happens when the mail is undeliverable. I get a failure notice to my inbox but these can be in the hundreds so its difficult to manually go through and delete from the database.
Is there anyway to "catch" the failed to send emails and then feed them back in to a query to delete from the database?
Someone once did a presentation on this at a function I attended. The approach was:
when sending mail, use a special email address in the failto attribute.
write a .cfm file that uses the cfpop tag to read mail sent to this address. (This may have been before the cfexchange tag was available)
add code that reads Delivery Failure Notfications and extracts the email addresses.
do something about those addresses
The presenter ran this file as a scheduled job.
#Dan Bracuk's answer above is the closest thing to a good answer you're probably going to get. Here's why: The CF server isn't delivering the mail, per-se. It's just handing the mailpiece off to a real mail server (even if that server runs on the same machine) for delivery. After it's accepted, CF's job is done. Non-delivery at this stage does not reflect on the quality of the address anyway, but rather the connection between your CF server and the mail server.
From there, it's spooled again, by the mail server. Sometimes a recipient's domain will accept email and ask questions later. The only way to know if an email delivery has failed is to wait for a Non-Delivery Report (email) to be sent to the failto (if used) or from address. This can come from "your" mail server, or a mail server for the recipient's domain. Depending on your mail server delivery retry options and third-party delays, this can take a day or more. If you want to do this yourself, you'll have to write a routine to POP and read the email from the account(s), and analyze them to determine if they are NDRs, and what type. Non-delivery Reports can indicate hard or soft bounces, blocks, delays, or gateway conditions. Obviously, many of these are not "throw it out" situations, so you'll have to parse them for SMTP codes http://www.serversmtp.com/en/smtp-error and keywords to determine if you should drop or mark the email address.