PHP: view unsuccessful emails - mysql

I'm trying to figure out how to display a list of unsuccessful emails sent and a way to test it out.
I can display a list of the emails that were sent, but I'm unsure on how to retrieve the list of emails that were unsuccessfully sent out.
Here is what I'm using to retrieve it from the mysqldb:
//get the email address list
$query = "SELECT email FROM users
WHERE id IN (SELECT participant_id FROM roster AS ur WHERE ur.roster_id=".$roster['roster_id'].")";
$result = mysql_query($query);
$emailstring2 = "";
$email2 = $result;
while ($row = mysql_fetch_object($email2)){
$emailstring2 .= $row->email. "\n ";
}
In the message section, I retrieve it via:
$message .="Successful emails: \n".$emailstring2." \r\n";
How would I achieve this?

One keyword will get you the ones not sent: NOT
WHERE id NOT IN

You can't do this from PHP in a simple manner like this.
Think of it as a letter going through the postal service. All you can do is give the letter to the postman and hope that it reaches its destination. The postman will not come back and tell you if delivery was successful, or if the letter was actually read by the recipient. PHP's mail() function (and its derivatives) return TRUE to indicate that the message was accepted for delivery attempts, not that it was successfully delivered. (Delivery may not happen for hours or days.)
As a result, the best you can do is approximate delivery notification. There are a few ways you can do this:
Use a tracking pixel in the email that gets pinged when the user
opens the message. However, given that most email clients nowadays
default to "do not show images," I think this technique is rather
unreliable.
Send each message with a bounce address unique to the recipient. If
the message can't be delivered, it will return to the custom address
-- and that return message can be used to indicate that the original recipient's email address is no good. This is probably the most accurate method but is not simple to configure.
Use return receipts. Like tracking pixels, I think most email clients
default to never send these, so this is likely unreliable as well.
Use delivery status notification. This will require using a server
that supports it and sending to a server that supports it.
Send your mails through a service that will do this sort of tracking for you. (E.g. MailChimp or Constant Contact)

Related

Is there a way to temporarily override Moodle's SMTP settings in a custom PHP script?

For reasons too complex to disclose here, a client of mine has requested that we develop a custom notifications script (installed under the Moodle root as a plain .php script) that runs on a cron and scans certain activities in Moodle (3.11) in order to send notifications to students (but only in one specific course) when other students are posting/participating in those other activities.
My complication comes in when trying to send emails in this notifications script using Moodle's internal mailing system, which I understand is a custom implementation of PHPMailer. The client wants the emails sent by this script to come through a different email address than the official one used by the rest of the Moodle site. So, while all regular Moodle emails (password resets, etc.) should come from "original#example.com", they want the custom emails in this script to come from "new#example.com" instead.
Example:
// prepare variables
$subject = "subject line";
$body = "some body text";
$toUser = $DB->get_record('user', array('email' => 'somestudent#example.com'));
$fromUser = $DB->get_record('user', array('email' => 'new#example.com'));
// TO DO: swap out Moodle SMTP settings - if possible?
// send email
$success = email_to_user($toUser, $fromUser, $subject, '', $body);
I am currently using the email_to_user() method in Moodle but, by changing the "from user" value (as shown above), can only change the "name" of the sender, not the email address it actually sends from. So, the result is an email with sender/header info that looks like "Custom User (via Moodle Site) original#example.com" rather than the default which is essentially "Moodle Site original#example.com".
What I actually want to appear is "Custom User new#example.com". To do this, I understand that I would need to swap out the SMTP settings prior to sending.
Is there a way to temporarily use different SMTP settings in Moodle, without overwriting the ones in the database?
If not, is there some other way or repurposing Moodle's existing PHPMailer to send emails using manual SMTP credentials - such as creating a new instance of PHPMailer using the same code packaged within Moodle by in which I can specify custom SMTP settings?
After digging through the files in Moodle's messaging and core libraries, as well as the PHPMailer docs, I came up with the following solution. This still piggybacks off of Moodle's internal mail system (PHPMailer), but is a much more direct way of creating a PHPMailer instance. Because this bypasses a lot of Moodle's additional functions, I was not able to call email_to_user() and this required manually configuring a lot of settings that Moodle would normally take care of. But, in the end, I am able to send email from the script under my Moodle webroot directory without having to install, configure, or maintain a separate mail sending library (i.e. a separate version of PHPMailer).
// create ne PHPMailer instance and configure as needed
$mail = get_mailer();
$mail->Sender = 'new#example.com';
$mail->Host = "smtp.host.com";
$mail->Port = "587";
$mail->IsSMTP();
$mail->SMTPSecure = "tls";
$mail->SMTPAuth = true;
$mail->setLanguage("en");
$mail->SetFrom("new#example.com","New Name");
$mail->Username = "new#example.com";
$mail->Password = "password";
$mail->AuthType = "Login";
$mail->IsHTML(true);
For each email that needs to go out, I then just call a few functions to update the required parameters.
// clear existing recipient list before forming new email
$mail->ClearAllRecipients();
// form new email by specifying only basic attributes
$mail->Subject = "Email Subject Line";
$mail->Body = "This is a new text body.";
// address directly to student's email
$mail->addAddress('recipient#example.com');
// send email
$success = $mail->send();

How do I keep "MailApp.sendEmail" emails with the same subject threaded?

I've written a script that sends an hourly email to me using:
MailApp.sendEmail("john#doe.com", "Status Update", currentStatus);
My only gripe is that every message I get is treated as a separate thread, despite the subject lines all being the same. I'd prefer if all were threaded so I can see the stream of messages in one place.
Is there any way to have new status messages appended to the same thread?
Will this require using GMailApp functions instead?
EDIT (2016-08-26): I have solved my problem using the following method/workaround:
Include a unique "marker" somewhere in the status message. I use a static UUID that I generated online.
Use GmailApp.search() to find the thread with the status message(s) by looking for the unique marker.
Use GmailApp.reply() to add a new status message to the thread.
This keeps all the status messages together as desired. Perhaps there's a more elegant way to do this but this works...

How to make MediaWiki account registrations only allow unique emails?

How can I set it so that MediaWiki will not allow a single email address to create multiple accounts? A spambot just created 5 accounts with a single email.
I've looked for configuration settings or extensions, but haven't been able to find one.
A related issue to this is the annoying creation of spam accounts with usernames similar to JameeiohpbrxvlsHeadlon.
Spam prevention measurements work quite well, as no actual spam articles are created, but only spam accounts. I have TorBlock, ConfirmEdit and SimpleAntiSpam installed to prevent spam accounts from being created, but this appears to fail.
This is not likely to be a very effective anti-spam strategy. Most spambots smart enough to register accounts with valid e-mail addresses are likely also smart enough to try a new address if the registration fails.
Personally, I've found the most effective anti-spam solution for small wikis to be ConfirmEdit with QuestyCaptcha. Just configure ConfirmEdit to require a CAPTCHA for account creation, so that you won't get spam accounts. The questions don't need to be hard to answer — indeed, they can be absolutely trivial, as long as they're unique to your site.
That said, you could do what you suggest by writing an AbortNewAccount hook to look up the user's e-mail address in the database and fail if you find a match, something like this (untested!):
$wgHooks['AbortNewAccount'][] = 'disallowDuplicateEmails';
function disallowDuplicateEmails( $user, &$message ) {
$email = $user->getEmail();
if ( !$email ) return true; // allow empty e-mail
$dbr = wfGetDB( DB_SLAVE );
$name = $dbr->selectField( 'user', 'user_name',
array( 'user_email' => $email ),
__METHOD__ );
if ( $name !== false) {
$message = wfMessage( 'signup-dup-email', $email, $name )->text();
return false;
}
return true; // no match
}
You'll also need to create the system message page MediaWiki:signup-dup-email, with content something like this:
The e-mail address <tt>$1</tt> is already used by [[User:$2|$2]].
Note that there are at least two potential issues with such a check:
It can allow people to "fish" for e-mail addresses of your users (something that MediaWiki normally treats as private information) by trying to register a new account with an address they suspect might belong to an existing user. This could be somewhat mitigated by omitting the username from the error message, but that would still leak the information that someone is using the address.
The code above doesn't check whether the address has been confirmed or not (and checking that would rather defeat its purpose, unless you also require all users to confirm their e-mail address), and so a malicious person could prevent someone else from registering with their e-mail address by creating a dummy account with the same address.
However, getting around the check would actually be rather easy, since a) it checks for an exact match, so e.g. just changing the capitalization of the host name would be enough to make the check pass, and b) it doesn't prevent users from changing their e-mail address to whatever they want after registering, anyway. Both of these holes could be blocked, but it would require more effort.

How to setup an SMS alert to website owner when a customer fills in a form?

Been doing some research on how to setup an SMS alert straight to the website owner's (our customer) phone when a website visitor fills in a form on his website. Obviously we're happy to sign up to a provider and pay a few cents for each message - not expecting this to be a freebie service.
A lot of the google results you get for this deal with bulk texting out to the many recipients which isn't what we're looking at here.
So what's the simplest small-scale way to achieve this via HTML and simple scripting?
This daniweb forum post offers clear and simple instructions using Coldfusion and that's fine but as it's 7 years old we wonder if things have moved on and are there better suggestions?
We'd be happy to script it very simply through ASP.NET or PHP or something else, but hoping to keep it lightweight, since this is a very simple website belonging to a small business.
I am working on a similar thing for my company.
We use a GSM modem such as: ZTE MF668A
It is a USB adapter which you can insert a SIM card into.
We purchased an SMS only plan, which is like $15 a month and you can send unlimited SMS. However the set up might be a bit more complicated than just using a bulk SMS service.
You can set up Diafaan SMS Server (http://www.diafaan.com/) on the computer with the GSM Modem to accept emails for a particular domain. (e.g. ours is #sms.com). Our exchange server forwards email to the Diafan Server. Diafaan will take the email and convert it to an SMS and send it using the GSM modem.
In you php code, you can use PHPMailer (http://phpmailer.worxware.com/) to construct an email and set the mail to address to be #sms.com.
You use it something like this:
ini_set("sendmail_from","user#company.com");
ini_set("SMTP","smtp.company.com");
require("PHPMailer/class.phpmailer.php");
$mail = new PHPMailer();
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp.company.com"; // specify main and backup server
$mail->SMTPAuth = false; // turn on SMTP authentication
//$mail->Username = "name"; // SMTP username
//$mail->Password = "password"; // SMTP password
$mail->From = "user#company.com";
$mail->FromName = $salesPerson;
$mail->AddAddress("user2#company.com", "Pricing");
$mail->AddReplyTo("user#company.com", "User2");
$mail->AddBcc($salesPersonEmail, $salesPerson);
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = $subject;
$mail->Body = $body;
if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
There are also companies that offer SMS services such as PCSMS where you get 100 SMS per month for a fee. Then you just construct an email and send it to #pcsms.com.au. This is probably the easiest way to do it and is the way we used to do it, but the way we do it now is much cheaper.
Disclaimer, I do developer evangelism part time at Nexmo.
While you can setup a GSM modem to send SMS messages, it's likely easier (and depending on your usage, cheaper) to use a SMS API. Here are a few providers - pricing is in cents per message (depends on the API and destination, but hovers around a cent or two). You may be required to provision a virtual number - pricing there is generally dollars/month (again, depends on API and destination, hovers around a dollar or two).
Nexmo
Twilio
Tropo
If you're sending internationally, I think your best would be Nexmo. Or if you see any need to accept incoming messages in the future, Nexmo's pricing model will help you there.
All three APIs are straight forward REST/HTTP APIs - as long as whatever language you're using server side can make a web request, you should be able to send an SMS.
Eventually we used Esendex. Good support from them, decent code samples and plenty of mileage in the free trial (which in fact they were happy to extend when we asked).

EWS Body of Email coming back empty?

We are in the process of converting a batch job that processes our bounced emails that we send. We are switching from Redemption to EWS (just upgraded to Exchange 2010 from Exchange 2003). As you know bounced emails come in different forms. I have been able to work through all the test case emails i've got except for the ones that come in the form of:
Your message did not reach some or all of the intended recipients.
Subject: Hello
Sent: 4/01/2012 8:16 AM
The following recipient(s) cannot be reached:
hi#foo.com on 4/01/2012 8:19 AM
The e-mail system was unable to deliver the message, but did not report a specific reason. Check the address and try again. If it still fails, contact your system administrator.
smtp.mydomain.com #5.0.0 smtp; 5.3.0 - Other mail system problem 554-"delivery error: dd This user doesn't have a foo.com account (hi#foo.com) [-5] - mail.foo.com" (delivery attempts: 0)>
This is what is displayed in outlook. When i read the email with EWS the Body is empty. I need to look at the information above when i get the email with EWS. The emails have an attachment (which is the original email) though it doesn't look that way in outlook. I've tried to look at almost all the properties that comes back from EWS and have yet been able to find the text above. Redemption allow you to look at this info using ReportText. What we are specifically looking for is the email error delivery code. We do different things based on this code.
Edit: To be clearer the Body Property on my other test cases isn't empty. I'm loading the emails like:
Dim emailPset = New PropertySet(BasePropertySet.FirstClassProperties)
emailPset.RequestedBodyType = BodyType.Text
Dim f = EmailMessage.Bind(email.Service, email.Id, emailPset)
Update1: After some research it looks like i need to be able to read the Recipients table of the message in the PR_NDR_STATUS_CODE & PR_REPORT_TEXT fields. Still searching if there is a way to do this in EWS.
We were able to get enough info the
smtp.mydomain.com #5.0.0 smtp; 5.3.0 - Other mail system problem 554-"delivery error: dd This user doesn't have a foo.com account (hi#foo.com) [-5] - mail.foo.com" (delivery attempts: 0)>
part which is what we needed by telling the object to load the MIME content.
Definitely not the most straight forward API to use but hopefully we don't hit any more hickups.