Dokan woocommerce, where is {site_name} in email placeholder

Sometimes can happen that the email sent through woocommerce have incorrect data. Where are placeholders data stored, for instance {site_name}, {site_address}, {order_number}, used in Dokan email templates? And, how to modifify {site_name} placeholder?

In my case {site_name} placeholder value was referring to an old site name, still present after a migration, due to this I bumped into the necessity of change placeholder value.

Uno screenshot del file wp-config.php dove è presente il prefisso del nome delle tabelle del database.
A screenshot WordPress wp-config.php file, where the database table prefix is defined.

To get the job done I was obliged to do the modification at mariadb/mysql database level. More specifically “{site_name}” was defined in “PREFIX_options” table, where PREFIX is your database table prefix defined in wp-config.php file at installation time.

The option to find out in my case was “woocommerce_email_from_name“, that represents {site_name} placeholder in Dokan email templates.

I came across it through phpmyadmin search functionality, searching for the name, the wrong one I want to replace, appearing on the email sent to users.

HINT!

The aim of this post is to explain how to replace Dokan email template placeholders ({site_name}), if you are trying to customize Dokan email templates, you can check out this link: https://wedevs.com/docs/dokan/tutorials/customize-e-mail-template/

An example of how Dokan is translating placeholder into bare text is the method trigger, defined in plugins/dokan-pro/modules/rma/includes/emails/class-dokan-rma-send-coupin-email.php php file:

<?php
/**
     * Trigger the sending of this email.
     *
     * @param int $product_id The product ID.
     * @param array $postdata.
     */
    public function trigger( $coupon, $data ) {
        if ( ! $this->is_enabled() || ! $this->get_recipient() ) {
            return;
        }

        $this->object = $coupon;

        if ( $data ) {
            $coupon_id      = isset( $data['request_id'] ) ? $data['request_id'] : '';
            $vendor_id      = isset( $data['refund_vendor_id'] ) ? $data['refund_vendor_id'] : '';
            $vendor         = dokan()->vendor->get( $vendor_id );
            $customer_email = $coupon->get_email_restrictions();
            $customer_email = is_array( $customer_email ) ? $customer_email[0] : $customer_email;
        }

        $this->find['site_name']      = '{site_name}';
        $this->find['vendor_name']    = '{vendor_name}';

        $this->replace['site_name']   = $this->get_from_name();
        $this->replace['vendor_name'] = $vendor->get_name();
        $this->replace['coupon_id']   = $coupon_id;

        $this->setup_locale();
        $this->send( "{$customer_email}, {$this->get_recipient()}", $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
        $this->restore_locale();
    }

In particoular, pay attention at these two lines:

...
$this->find['site_name']      = '{site_name}';
...
$this->replace['site_name']   = $this->get_from_name();
...

The get_from_name method is defined in a superclass and is the function in which the substitution is done.

I strongly suggest you to explore source code through Visual Studio Code or an equivalent product, to better understand how your specific case works.

Fell free to post a comment to submit your case.

Dump calendars from Zimbra command line

An easy php snippet to produce the commands necessary to backup Zimbra calendars

Recently I bumped into a migration from Zimbra to another mail system provider; this migration regarded all accounts including, of course, them calendars, contacts and task.

We decided to use a tool named Transend that was among the suggested by AWS support, but for non interesting reasons, we also needed to get the calendars out of Zimbra.

Via zimbra cli it is very easy to do that:

/opt/zimbra/bin/zmmailbox -z -m yourmail@example.com getRestURL "/Calendar/?fmt=ics" > /tmp/Calendars/youremail.ics

But … I had a lot accounts to care about, nevertheless I am normally very lazy in repeating dummy commands.
So I decided to write this little PHP snippet to produce the rows I need and than copy and past the result on zimbra cli.

The Script

Take a look at the following example with 4 accounts:

<?php

/**
 * You can of course use a simpler array,
 * but the file name with a @ is not the best you can have in your life.
 *  
 * */
$accounts = [
'peter.pan'=>'peter.pan@example.com',
'bruce.banner'=>'bruce.banner@example.com',
'clark.kent'=>'clark.kent@example.com',
'mario.merola'=>'mario.merola@example.com',
];

foreach($accounts as $account => $email){
	echo "/opt/zimbra/bin/zmmailbox -z -m $email getRestURL \"/Calendar/?fmt=ics\" > /tmp/Calendars/$account.ics" . "\n";
}

the result will be:

/opt/zimbra/bin/zmmailbox -z -m peter.pan@example.com getRestURL "/Calendar/?fmt=ics" > /tmp/Calendars/peter.pan.ics
/opt/zimbra/bin/zmmailbox -z -m bruce.banner@example.com getRestURL "/Calendar/?fmt=ics" > /tmp/Calendars/bruce.banner.ics
/opt/zimbra/bin/zmmailbox -z -m clark.kent@example.com getRestURL "/Calendar/?fmt=ics" > /tmp/Calendars/clark.kent.ics
/opt/zimbra/bin/zmmailbox -z -m mario.merola@example.com getRestURL "/Calendar/?fmt=ics" > /tmp/Calendars/mario.merola.ics

Now I am ready to copy and paste those lines on my Zimbra terminal and say “have a good week-end!” to the world.

Apache2 certificates does not match

If your Apache2 is blocked (status inactive) because of SSL certificates’ issue, this article can be the solution you are looking for.

You can occasionally stumble in a problem of certificates mismatching, in other words you are probably using a certificate that is not related with the given private key.

It can happen especially if you are renewing your certificates manually, more over you can experience this issue when you use Certera or more generally letsencrypt certificates.

The symptoms are that the webserver is not active (inactive) and all your virtual hosts are not reachable on both 80 and 443 ports.

Furthermore the web server (apache2 in our case) is not up and running.

How to deal with that?

Simple, use the right certificates!

How can I be sure about the certificate mismatching?

Simple again 🙂

You can use this commands

openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in privkey.pem | openssl md5

You will be ok when the resulting md5 string is the same for both certificates.

Useful details and references

Note that your certificate can have .crt extension rather than the .pem one.
Also the privkey.pem can have a different name with .key extension.

To check if your apache2 is working correctly (i.e. status active) you can run this command:

systemctl status apache2

To check if there is some error you can use the command

tail -f /var/log/apache2/*.log

The solution has been ispired by this very useful article on Digicert.com.

Certera.io notification via Slack webhook on Rocketchat

Certera is a software that allows you, as sysadmin, to centralize the production and the distribution of SSL certificates for your websites and applications.

If you landed here it’s because you probably need to go deeper on some topic as notifications from Certera when something is going wrong or, more often, when a certificate is about to expire.

An easy and effective way to get notifications from Certera is on your Slack chat with a webhook, but what happen if you or your company are using Rocket Chat as instant messaging system?

I personally opened a ticket (feature request) to Certera developers (that are very reactive) in which I asked for a RocketChat integration for Certera.io.

I’m sure they will solve it soon, but meanwhile I will give you some hint to make the things done with the Slack Webhook, in order to translate the request from Slack to RocketChat.

Let’s begin then.

Step1 – Create a Rocketchat webhook

  • Go to Admin panel -> Integration
  • Create an Incoming Webhook dedicated to certera
  • Configure it
  • Activate the script and put there the following code (gotten in Rocket Chat Integrations page)
/* exported Script */
/* globals console, _, s */

/** Global Helpers
 *
 * console - A normal console instance
 * _       - An underscore instance
 * s       - An underscore string instance
 */

class Script {
  /**
   * @params {object} request
   */
  process_incoming_request({ request }) {
    // request.url.hash
    // request.url.search
    // request.url.query
    // request.url.pathname
    // request.url.path
    // request.url_raw
    // request.url_params
    // request.headers
    // request.user._id
    // request.user.name
    // request.user.username
    // request.content_raw
    // request.content

    // console is a global helper to improve debug
    console.log(request);

    return {
      content:{
        text: request.content.blocks[0].text.text + "\n" +  request.content.blocks[1].text.text
        // "attachments": [{
        //   "color": "#FF0000",
        //   "author_name": "Rocket.Cat",
        //   "author_link": "https://open.rocket.chat/direct/rocket.cat",
        //   "author_icon": "https://open.rocket.chat/avatar/rocket.cat.jpg",
        //   "title": "Rocket.Chat",
        //   "title_link": "https://rocket.chat",
        //   "text": "Rocket.Chat, the best open source chat",
        //   "fields": [{
        //     "title": "Priority",
        //     "value": "High",
        //     "short": false
        //   }],
        //   "image_url": "https://rocket.chat/images/mockup.png",
        //   "thumb_url": "https://rocket.chat/images/mockup.png"
        // }]
       }
    };

    // return {
    //   error: {
    //     success: false,
    //     message: 'Error example'
    //   }
    // };
  }
}

Configure and activate everything.

Step2 – Put the webhook url to Certera.io admin web panel

In Certera.io notification page you will find the Slack webhook URL, put what you have produced on Rocketchat side and activate the notification.

Done!

Explaination

You have certainly noticed that the most of the source code is commented (//), infact the most important part of the code is:

        text: request.content.blocks[0].text.text + "\n" +  request.content.blocks[1].text.text

This code translates the payload of the POST request gotten via webhook by Rocket Chat.

The “translation” is done according to the template I found in Certera.io source code.

Dump database Mysql/Maria DB in file separati

Come eseguire un export su file di tutti i database su un server Mysql da riga di comando.

Avevamo già parlato di come effettuare il backup di tutti i database mysql per mezzo di uno script bash, ma di recente un mio collega mi ha segnalato una soluzione, che secondo me è molto più elegante.

Si tratta di un singolo comando da eseguire sulla linea di comando con i pipe (questo è il pipe “|”).

Ecco il comando:

mysql -N -e 'show databases' | while read dbname; do mysqldump --complete-insert --routines --triggers --single-transaction "$dbname" > "$dbname".sql; [[ $? -eq 0 ]] && gzip "$dbname".sql; done 

Vediamo i comandi nel dettaglio; per farlo scriviamo sulla cli quanto segue:

mysql --help

-N, –skip-column-names
Don’t write column names in results.

L’opzione -N non fornisce in output il nome della colonna, nel nostro caso la lista dei database sarà quindi priva di intestazione ed utilizzabile nel while successivo al primo pipe.

-e, –execute=name Execute command and quit. (Disables –force and history
file.)

L’opzione -e, consente di eseguire il comando tra apici, ovvero “‘show databases'”.

La parte che segue il pipe (“|”) prende come input l’output di quello che lo precede, consentendo di effettuare un ciclo while sul nome di ogni database e di fare un dump con il comando mysqldump.

Forse si può fare meglio, ma il kata-programming non va abusato e chi si accontenta gode!

Detto questo se vi mettete a smanettare con quello script, postate tutto nei commenti.