Jump to content
  • 0
DennisHermannsen

Use value for variable in hook

Question

Hi.

I'm currently building a module that allows customers to receive an email notification once a Network Issue is opened/edited and that issue affects one or more of their products. Currently, my config looks like this:

function networkissuenotification_config()
{
    return [
        // Display name for your module
        'name' => 'Network Issue Notification',
        // Description displayed within the admin interface
        'description' => 'This module sends an email to the client if a network issue has been created or edited.',
        // Module author name
        'author' => 'Dennis Hermannsen',
        // Default language
        'language' => 'english',
        // Version number
        'version' => '1.0',
        'fields' => [
            // a text field type allows for single line text input
            'Email Template Name' => [
                'FriendlyName' => 'Email Template Name',
                'Type' => 'text',
                'Size' => '25',
                'Default' => 'Network Issue Email',
                'Description' => 'This field defines which email the client should receive.',
            ],
        ]
    ];
}

How would I use the 'Email Template Name' variable in hooks.php? I can use $vars['Email Template Name'] in the admin output, but $vars is completely empty when used in hooks.php.

Share this post


Link to post
Share on other sites

15 answers to this question

Recommended Posts

  • 0

You'll need to get that variable with a query. The $vars in action hooks varies depending on hook point. It could be empty, return a just an ID or an entire set of data but there's nothing about modules.

Share this post


Link to post
Share on other sites
  • 0
14 hours ago, DennisHermannsen said:

I'm currently building a module that allows customers to receive an email notification once a Network Issue is opened/edited and that issue affects one or more of their products.

a-ha that explains why you've been viewing my network issues threads and hooks recently. 💡

would it really need to be a module though? would they need to choose the template to use ??

there's already an existing commercial hook that supposedly does it (no idea if it still works though as it's 7 years old) for £12GBP... I would assume that it's just a NetworkIssueAdd / Edit hook that triggers the sending of the appropriate email template to the affected users, or in the case of that hook, everyone if it s not a server specific issue.

Share this post


Link to post
Share on other sites
  • 0
3 minutes ago, brian! said:

a-ha that explains why you've been viewing my network issues threads and hooks recently. 💡 

I actually just came across it on the forums before I started making the hook yesterday and thought it was a good idea. I had never thought about showing open network issues on the client area! It also reminded me that I months ago thought about creating a hook that would allow users to receive email notifications about network issues 😄

5 minutes ago, brian! said:

would it really need to be a module though? would they need to choose the template to use ??

Definately not - the module is mostly just a hook 🙂 I just wanted to mess with building a module for fun, and this was good practice for a newbie 😛 I'm still thinking about making the module publicly available.

7 minutes ago, brian! said:

I would assume that it's just a NetworkIssueAdd / Edit hook that triggers the sending of the appropriate email template to the affected users, or in the case of that hook, everyone if it s not a server specific issue. 

That's also exactly how my module works (and I'm a bit surprised to say it works lol). The only issue is that there's no way to use WHMCS 'Mass Email' feature, and sending 2000 emails through the SendEmail API  will most likely cause a timeout 😕

I'm still confused as to why module hooks can't use module variables. It seems like such a logical thing 😄

Share this post


Link to post
Share on other sites
  • 0
2 hours ago, DennisHermannsen said:

That's also exactly how my module works (and I'm a bit surprised to say it works lol). The only issue is that there's no way to use WHMCS 'Mass Email' feature, and sending 2000 emails through the SendEmail API  will most likely cause a timeout

Naaaaah! I don't get why so many people focus on SendEmail API 😛 When you use SendEmail WHMCS simply "transfers" your request to PHPMailer that can be found in vendor/phpmailer/phpmailer therefore,  especially if you need to send so many emails, skip the API and send them through PHPMailer like follows (it is just an untested example)

<?php

// Autoload PHPMailer
include ROOTDIR . '/vendor/phpmailer/phpmailer/PHPMailerAutoload.php';
// Load email details from tblconfiguration
$conf = GiveMeEverythingINeedToSendAnEmail('CompanyName', 'Email', 'MailType', 'SMTPHost', 'SMTPUsername', 'SMTPPassword', 'SMTPort');
// Don't forget to decrypt the password
$conf->SMTPPassword = Decrypt($conf->SMTPPassword);

// Init PHPMailer
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';

$clients = array(
                array('email' => 'mike@example.com', 'name' => 'Mike Tyson'),
                array('email' => 'sarah@example.com', 'name' => 'Sarah Connor'),
                array('email' => 'arnold@example.com', 'name' => 'Arnold Schwarzenegger'),
            );

// Let's send an email to clients
foreach ($clients as $client)
{
    try
    {
        // Send via SMTP
        if ($conf->MailType == 'smtp')
        {
            $mail->IsSMTP();
            $mail->Host       = $conf->Host;
            $mail->SMTPAuth   = false;
            $mail->Port       = $conf->SMTPort;
            $mail->Username   = $conf->SMTPUsername;
            $mail->Password   = $conf->SMTPPassword;
        }
        // Send without SMTP
        else
        {
            $mail->IsMail();
        }

        $mail->AddAddress($client['email'], $client['name']);
        $mail->SetFrom($conf->Email, $conf->CompanyName);
        $mail->Subject = 'I\'ll be back';
        $mail->MsgHTML('Dear ' . $client['name'] . ',<br><br>I hate you<br><br>Best regards');
        $mail->Send();
    }
    catch (phpmailerException $e)
    {
        //echo $e->errorMessage(); //Pretty error from PHPMailer
    }
    catch (Exception $e)
    {
        //echo $e->getMessage(); //Boring error from anything else!
    }
}

That's how you spam emh... mass-mail customers. Of course you'll need to put some limitations (eg. send 5 emails every 30 seconds) or you'll be blacklisted.

Share this post


Link to post
Share on other sites
  • 0

@Kian wouldn't that still cause an issue with timeouts?

I'm looking for a way to send these in batches in the background - kind of like how the Mass Email works.

Share this post


Link to post
Share on other sites
  • 0

Use sleep() + set_time_limit().

With sleep, you delay execution this way you can send 5 emails, wait 30 seconds, send 5 emails, wait 30 seconds and so on till all emails have been sent. This helps to prevent getting blacklisted.

Each time you call sleep, you will reset timeout with set_time_limit. I quote: When called, set_time_limit() restarts the timeout counter from zero. In other words, if the timeout is the default 30 seconds, and 25 seconds into script execution a call such as set_time_limit(20) is made, the script will run for a total of 45 seconds before timing out.

 

Share this post


Link to post
Share on other sites
  • 0

The main reason I was using the SendEmail API was that I could use it to send emails that was built as email templates. I've already configured the module to send emails using SwiftMailer with the AntiFlood plugin (which allows configuring how many emails to send at a time).

I can't really think of a way to send these emails (including variables) without SendEmail. Any ideas, @Kian or @brian!?

Share this post


Link to post
Share on other sites
  • 0

Given that you can freely use SendEmail if you want to, you can still use Email Templates and variables also with PHPMailer. It's a bit boring process but that's part of our job 😛 Query db, str_replace. Job done.

<?php

// Spoiler alert !!! THIS IS AN EXAMPLE !!! It won't work for real

// Load your Email Template (any language)
$EmailTemplate = 'SELECT subject, message, language FROM tblemailtemplates WHERE name = "Your Email Template"';

/*
 * Use language as key like in the following example
 *
 * $EmailTemplate['italian'] = array('subject' => 'Benvenuto', message => 'Gentile {$clientname}<br>La tua mail è {$email}');
 * $EmailTemplate['english'] = array('subject' => 'Welcome', message => 'Dear {$clientname}<br>Your email is {$email}');
 */

// Load your Clients
$Clients = array(
                array('email' => 'mike@example.com', 'name' => 'Mike Tyson', 'language' => 'italian'),
                array('email' => 'sarah@example.com', 'name' => 'Sarah Connor', 'language' => 'english'),
                array('email' => 'arnold@example.com', 'name' => 'Arnold Schwarzenegger', 'language' => 'english'),
            );

// Autoload PHPMailer
include ROOTDIR . '/vendor/phpmailer/phpmailer/PHPMailerAutoload.php';
// Load email details from tblconfiguration
$conf = GiveMeEverythingINeedToSendAnEmail('CompanyName', 'Email', 'MailType', 'SMTPHost', 'SMTPUsername', 'SMTPPassword', 'SMTPort');
// Don't forget to decrypt the password
$conf->SMTPPassword = Decrypt($conf->SMTPPassword);

// Send emails
foreach ($Clients as $Client)
{
	try
	{
		// Send via SMTP
		if ($conf->MailType == 'smtp')
		{
			$mail->IsSMTP();
			$mail->Host       = $conf->Host;
			$mail->SMTPAuth   = false;
			$mail->Port       = $conf->SMTPort;
			$mail->Username   = $conf->SMTPUsername;
			$mail->Password   = $conf->SMTPPassword;
		}
		// Send without SMTP
		else
		{
			$mail->IsMail();
		}

		$mail->AddAddress($client['email'], $client['name']);
		$mail->SetFrom($conf->Email, $conf->CompanyName);
		$mail->Subject = $EmailTemplate[$Client['language']]['subject'];
		// Populate Email Template variable
		$mail->MsgHTML(str_replace(array('{$clientname}', '{$email}'), array($Client['name'], $Client['email']), $EmailTemplate[$Client['language']]['message']));
		$mail->Send();
	}
	catch (phpmailerException $e)
	{
		//echo $e->errorMessage(); //Pretty error from PHPMailer
	}
	catch (Exception $e)
	{
		//echo $e->getMessage(); //Boring error from anything else!
	}
}

This way every client will receive the email with correct language using Email Templates & variables. The reasons why I prefer to use PHPMailer instead of SendEmail are the following:

  • SendEmail doesn't support attachments 🤧
  • SendEmail doesn't allow to send emails from a different address 😟
  • With PHPMailer you more freedom 🤩 Dynamic CC, BCC, AltBody (non-HTML version) etc.

Share this post


Link to post
Share on other sites
  • 0
1 hour ago, Kian said:

$conf->SMTPPassword = Decrypt($conf->SMTPPassword);

Wait, is there any way to actually decrypt the SMTP password from the WHMCS settings? AFAIK, it can only be done using the cc encryption hash, and I haven't had any luck retrieving that? 😛

Also, I have a few if/else conditions in the email template, so the best solution would be to be able to parse the actual template the way WHMCS does.

Edited by DennisHermannsen

Share this post


Link to post
Share on other sites
  • 0

I could be wrong but Decrypt() and Encrypt() internal functions are not documented. For sure they were in past but I can no longer spot them. At least there are their API-equivalent: DecryptPassword and EncryptPassword.

Edited by Kian

Share this post


Link to post
Share on other sites
  • 0

🤣 no. It was just an example based on a method I get used to implement in my WHMCS projects to retrieve stuff from tblconfiguration from any place (module, hooks, pages, widgets...)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated