Categorieën
Hosting Linux PHP WordPress

WordPress e-mails SPF `neutral`

Veel WordPress website beheerders zullen wel eens meegemaakt hebben dat ze geen e-mailnotificatie kregen nadat een bezoeker een formulier had ingestuurd. Dit komt vaak doordat WordPress en het versturen van e-mails foutgevoelig is. Er kan namelijk op allerlei plekken iets fout gaan waardoor je als beheerder geen e-mailnotificatie binnen krijgt. In dit bericht zal ik een aantal scenario’s benoemen.

Formulieren plugin

Veel WordPress websites maken gebruik van een formulieren plugin. WordPress is namelijk standaard niet uitgerust met een formulieren functionaliteit. We maken bij Pronamic voornamelijk gebruik van de formulieren plugin Gravity Forms (affiliate link). Binnen Gravity Forms kunnen beheerders per formulier e-mailnotificaties instellen. Als een e-mailnotificatie niet binnen komt dan kan het zijn dat de e-mailnotificatie niet goed is ingesteld. Er is bijvoorbeeld een onjuist e-mailadres ingesteld of de e-mailnotificatie wordt alleen verstuurd bij bepaalde condities. Bij problemen is het daarom goed om altijd te controleren of e-mailnotificatie instellingen juist zijn. En of er misschien nog plugin updates beschikbaar zijn.

Standaard WordPress e-mail functie

WordPress is standaard uitgerust met een e-mail functie genaamd wp_mail(). Ontwikkelaars kunnen deze functie gebruiken voor het versturen van e-mails. Formulieren plugins zoals Gravity Forms maken vaak gebruik van deze functie. De wp_mail() functie maakt standaard gebruik van de PHPMailer bibliotheek. De PHPMailer bibliotheek maakt vaak weer gebruik van de PHP mail() functie. De PHP mail() functie roept vervolgens vaak weer de e-mail functionaliteit van het besturingssysteem aan. Binnen deze verschillende functies/technieken kan ook het één en andere fout gaan.

Maatwerk WordPress e-mail functie

De standaard WordPress e-mail functie kan door ontwikkelaars ook aangepast worden. Als iemand bijvoorbeeld geen gebruik wil maken van PHPMailer en/of de PHP mail() functie dan kan dat aangepast worden. Beheerders kunnen er bijvoorbeeld voor kiezen om e-mails te laten versturen door een e-mailprovider. Mijn collega Leo schreef op 29 februari 2016 in het bericht “4 gratis providers voor betrouwbare transactionele e-mails vanuit jouw WordPress website” hierover. Het voordeel van zo’n e-mailprovider is dat ze gespecialiseerd zijn in het versturen van e-mails. Deze partijen helpen je vaak ook om alle instellingen goed in te stellen.

  • Mandrill
  • SendGrid
  • Mailjet
  • MailGun
  • SparkPost
  • Postmark
  • SendinBlue

Toch kan er bij het gebruik van een e-mailproviders nog steeds van alles misgaan. Zo komt het soms voor dat WordPress niet goed kan communiceren met de betreffende e-mailprovider. Bijvoorbeeld doordat de e-mailprovider API even niet goed bereikbaar is. Daarnaast werken deze e-mailproviders vaak met abonnementen en limieten. Indien een limiet wordt bereikt kan het versturen van e-mails geblokkeerd worden. Verder zijn deze e-mailproviders vaak erg populair en werken ze met gedeelde IP-adressen. Doordat de diensten zo populair zijn komt het ook vaker voor dat hun IP-adressen op een blacklist staan.

SPF neutral

Om te testen of je WordPress installatie e-mails goed verstuurd kun je gebruik maken van de Check Email plugin van Chris Taylor en de mail-tester.com tool van MailPoet & AcyMailing. Via deze tools kun je controleren of e-mailbeveiliging technieken zoals SPF en DKIM goed zijn ingesteld. Op een website gehost bij SiteGround viel mij daardoor recent de volgende SPF-melding op:

spf=neutral (google.com: 69.175.69.92 is neither permitted nor denied by best guess record for domain of ********@esm35.siteground.biz) smtp.mailfrom=********@esm35.siteground.biz
Return-Path: <********@esm35.siteground.biz>

Het liefst zie je de spf=pass melding om meer zekerheid te hebben dat e-mails niet als ongewenst (spam) worden gezien. Na een zoektocht blijkt dat SiteGround standaard een @esm35.siteground.biz e-mailadres instelt als Return-Path. Hierdoor controleren e-mailservers of de server achter het esm35.siteground.biz adres wel e-mails mogen versturen namens de betreffende domeinnaam. Dit is neither permitted nor denied, dus niet toegestaan of geweigerd en daardoor neutral. Gelukkig kunnen we de Return-Path die SiteGround standaard instelt wel overschrijven. Tot 20 augustus 2016 deed WordPress dit standaard. Dit werd echter verwijderd omdat dit niet op alle hosting omgevingen goed werkt. Meer informatie hierover is te vinden in WordPress core Trac ticket 37736 (Git commit). Binnen een SiteGround hosting omgeving is dit echter geen probleem. De Return-Path kan bij SiteGround ingesteld via het php.ini bestand:

sendmail_path = "/usr/sbin/sendmail -t -i -f email@domeinnaam.tld"

Eventueel kan ook de “wp_mail return-path” plugin van Barnaby Puttick gebruikt worden.

Categorieën
Hosting Linux WordPress

WordPress network/multisite cron vervangen met Linux cron SiteGround

Veel WordPress ontwikkelaars zijn geen fan van de standaard WordPress cron functionaliteit. Vaak wordt daarom geadviseerd om de WordPress cron te vervangen met een Linux cron. De meeste artikelen adviseren om in wp-config.php de WordPress uit te schakelen via define( 'DISABLE_WP_CRON', 'true' ); en via cPanel of DirectAdmin een Linux cron in te stellen:

/usr/local/bin/php /home/user/public_html/wp-cron.php

Voor een eenvoudige WordPress installatie werkt dit vaak goed, maar binnen een WordPress network/multisite installatie wordt het vaak al lastiger. Als je je website host bij SiteGround is dit echter ook een fluitje van een cent. De volgende WP-CLI commando komt hier namelijk goed bij van pas:

wp site list --path=/home/user/public_html --deleted=0 --field=url | xargs -I {} wp cron event run --due-now --path=/home/user/public_html --quiet --url={}

Bovenstaand commando bestaat eigenlijk uit 2 commando’s, één voor het opvragen alle sites en één voor het uitvoeren van de verlopen cron events:

  1. wp site list --path=/home/user/public_html --deleted=0
  2. wp cron event run --due-now --path=/home/user/public_html --quiet --url={}

Met behulp van het xargs command geven we de output van het eerste commando door aan het tweede commando. Op die manier worden de verlopen cron events van alle (niet verwijderde) websites uitgevoerd.

Resources

Categorieën
Hosting PHP WordPress

SiteGround timeout verhogen

Veel WordPress gebruikers zullen wel eens tegen timeouts aanlopen. Vooral bij bulk acties in WordPress wil dit nog wel eens voorkomen. Gelukkig kan de timeout limiet vaak verhoogd worden via bijvoorbeeld een .htaccess bestand. Bij SiteGround kan de limiet verhoogd worden via onderstaande code:

# BEGIN Custom timeout
<IfModule mod_dtimeout.c>
	<Files ~ ".php">
		SetEnvIf Request_URI "edit.php" DynamicTimeout=3600
	</Files>
</IfModule>
# END Custom timeout

Bron: https://wordpress.org/support/topic/temporary-failure/

Categorieën
Hosting PHP WordPress

PHP 7 Cron Jobs bij SiteGround

Gebruikers van SiteGround weten waarschijnlijk wel dat SiteGround altijd bovenop nieuwe ontwikkelingen zit. Zo hadden ze PHP 7 al vrij snel beschikbaar gesteld aan hun gebruikers. Door een regel op te nemen in een .htaccess  bestand kan PHP 7 eenvoudig geactiveerd worden:

AddHandler application/x-httpd-php70 .php .php5 .php4 .php3

Meer informatie hierover is te vinden op de volgende SiteGround pagina’s:

Voor zover mij bekend werkt dit echter niet voor Cron Jobs die direct de PHP executable aanroepen via bijvoorbeeld:

/usr/local/bin/php /home/username/public_html/wp-cron.php

Nou is het vrij eenvoudig om de PHP 7 executable te gebruiken door bovestaande commando aan te passen:

/usr/local/bin/php70 /home/username/public_html/wp-cron.php

Dit resulteerde bij mij echter in de volgende fout:

Cannot load Zend OPcache - it was already loaded

Reden om even te informeren bij de SiteGround support afdeling:

PHP 7 Cron Jobs bij SiteGround

Helaas werd de chatsessie zomaar beëindigd en heeft SiteGround niet opnieuw contact met me opgenomen. Na een korte zoektocht kwam ik echter zelf een oplossing tegen:

Usage: php [options] [-f] <file> [--] [args...]
   php [options] -r <code> [--] [args...]
   php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
   php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
   php [options] -S <addr>:<port> [-t docroot]
   php [options] -- [args...]
   php [options] -a

  -a               Run as interactive shell
  -c <path>|<file> Look for php.ini file in this directory
  -n               No configuration (ini) files will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse and execute <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -S <addr>:<port> Run with built-in web server.
  -t <docroot>     Specify document root <docroot> for built-in web server.
  -s               Output HTML syntax highlighted source.
  -v               Version number
  -w               Output source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

  --ini            Show configuration file names

  --rf <name>      Show information about function <name>.
  --rc <name>      Show information about class <name>.
  --re <name>      Show information about extension <name>.
  --rz <name>      Show information about Zend extension <name>.
  --ri <name>      Show configuration for extension <name>.

Door de -n optie toe te voegen aan het commando was de foutmelding verdwenen.

/usr/local/bin/php70 -n /home/username/public_html/wp-cron.php
Categorieën
Hosting WordPress

WordPress SAVEQUERIES invloed op performance

Voor debug en ontwikkel doeleinden kan het soms handig zijn om alle WordPress queries op te slaan. Dit kan gerealiseerd worden door in je code de SAVEQUERIES constante op true te zetten. Vaak wordt dit toegevoegd aan het WordPress configuratie bestand wp-config.php. Er zijn echter ook plugins die deze constante op true zetten, bijvoorbeeld: Query Monitor. Het wil dan ook wel eens voorkomen dat maatwerk code de define( 'SAVEQUERIES', true ); definitie bevat. Voor productie omgevingen is dit echter vaak niet gewenst om dit impact kan hebben op de performance van een website. Het kan soms echter lastig zijn om te achterhalen waar de SAVEQUERIES constante op true is gezet. Gelukkig kan met grep eenvoudig gezocht worden naar alle bestanden met daarin SAVEQUERIES:

grep -r -H "SAVEQUERIES" *
Categorieën
Hosting Linux WordPress

Savvii VPS productie en staging

Gebruikers van een Savvii VPS hebben de mogelijkheid om SSH toegang te krijgen. Dit kan erg handig zijn om bijvoorbeeld snel een backup te maken of een kopie te maken van een website. Voor het opzetten van een nieuwe actuele staging omgeving kun je als volgt te werken gaan:

Productie | staging

Allereerst is het handig dat productie en staging omgevingen met elkaar kunnen communiceren via SSH. Hiervoor is het handig om een nieuwe SSH key aan te maken op de productie omgeving en deze toe te voegen aan de staging omgeving.

Productie

ssh user1@user1.savviihq.com

ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/pronamic_rsa

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/pronamic_rsa

Localhost

scp user1@user1.savviihq.com:~/.ssh/pronamic_rsa.pub ~/Downloads/pronamic_rsa.pub

scp ~/Downloads/pronamic_rsa.pub user2@user2.savviihq.com:~/tmp/pronamic_rsa.pub

Staging

ssh user2@user2.savviihq.com

cat ~/tmp/pronamic_rsa.pub >> ~/.ssh/authorized_keys

rm ~/tmp/pronamic_rsa.pub

Productie » staging

ssh user1@user1.savviihq.com

cd ~/wordpress/current

echo "wp-config.php" > staging-exclude.txt
echo "wp-content/infinitewp/backups" >> staging-exclude.txt
echo "wp-content/mu-plugins" >> staging-exclude.txt
echo "wp-content/mysql" >> staging-exclude.txt
echo "wp-content/uploads/2002" >> staging-exclude.txt
echo "wp-content/uploads/2003" >> staging-exclude.txt
echo "wp-content/uploads/2004" >> staging-exclude.txt
echo "wp-content/uploads/2005" >> staging-exclude.txt
echo "wp-content/uploads/2006" >> staging-exclude.txt
echo "wp-content/uploads/2007" >> staging-exclude.txt
echo "wp-content/uploads/2008" >> staging-exclude.txt
echo "wp-content/uploads/2009" >> staging-exclude.txt
echo "wp-content/uploads/2010" >> staging-exclude.txt
echo "wp-content/uploads/2011" >> staging-exclude.txt
echo "wp-content/uploads/2012" >> staging-exclude.txt
echo "wp-content/uploads/2013" >> staging-exclude.txt
echo "wp-content/uploads/2014" >> staging-exclude.txt
echo "wp-content/uploads/2015" >> staging-exclude.txt
echo "wp-content/uploads/backwpup*" >> staging-exclude.txt
echo "wp-content/uploads/gravity_forms" >> staging-exclude.txt
echo "wp-content/uploads/sites" >> staging-exclude.txt

# wp db export current.sql
mysqldump --user=user1 --password=******** --add-drop-table user1 > current.sql

rsync -avuz --exclude-from=staging-exclude.txt . user2@user2.savviihq.com:~/wordpress/current

Het staging-exclude.txt bestand kun je in principe eenmalig aanmaken en in bijhouden welke mappen niet mee hoeven naar de staging omgeving. In bovenstaand voorbeeld heb ik veel uploads mappen uitgesloten.

Staging omgeving

ssh user2@user2.savviihq.com

cd ~/wordpress/current

# wp db reset
# wp db import current.sql
# wp search-replace 'http://user1.savviihq.com' 'http://user2.savviihq.com'

mysql --user=user2 --password=******** user2 < current.sql

WP-CLI

Helaas werkt WP-CLI momenteel niet op onze Savvii VPS’en. Hierdoor is het exporteren en importeren van de database nog wat omslachtig. Met WP-CLI zou dit vereenvoudig kunnen worden wp db export, wp db reset, wp db import en wp search-replace.

Resources