Ab und an muss man unverständliche Dinge neu lernen. Der Versuch direkte Kalendereinladungen per WordPress zu versenden, endet im Disaster. Aber warum?

mail() ist eine PHP Funktion die Mails verschickt. wp_mail() ist die WordPress Funktion. wp_mail kann es aber nicht, da es den Code nicht korrekt formatiert und daher die Mails entweder mit einer ICS Datei ankommen, oder der Mailserver diese nicht lesen kann. Mit mail() umzusetzen ist möglich, aber ist aufwändig und nutzt nicht die WordPress Möglichkeiten.

Daher habe ich ein Zwitter gemacht. Ich nutze eine eigene Funktion, greife aber auf das Mailversandgerüst von WordPress zurück.

<?php
function sendOutlookInvitation($participants, $subject, $desc, $start_time, $end_time, $location='') {
	global $phpmailer;
	if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
		require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
		require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
		require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
		$phpmailer = new PHPMailer\PHPMailer\PHPMailer( true );

		$phpmailer::$validator = static function ( $email ) {
			return (bool) is_email( $email );
		};
	}

	$phpmailer->addAddress($participants[0]);
	foreach ($participants as $i => $attendee) {
		if ($i >= 1) $phpmailer->addCC($attendee);
	}

	$phpmailer->WordWrap = 50;
	$phpmailer->isHTML(true);

	$urlparts = parse_url(site_url());
	$organizer = $urlparts['host'];

	$text = "BEGIN:VCALENDAR\r\n".
		"VERSION:2.0\r\n".
		"PRODID:-//wukch-calender//mailer/NONSGML v1.0//EN\r\n".
		"METHOD:REQUEST\r\n".
		"BEGIN:VEVENT\r\n".
		"UID:" . md5(uniqid(mt_rand(), true)) . "wuk.ch\r\n".
		"DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z\r\n".
		"DTSTART:" . date('Ymd\THis', $start_time) . "Z\r\n".
		"DTEND:" . date('Ymd\THis', $end_time) . "Z\r\n".
		"SUMMARY:".$subject."\r\n".
		"ORGANIZER;CN=".$participants[0].":mailto:website@".$participants[0]."\r\n".
		"LOCATION:".$location."\r\n".
		"DESCRIPTION:".$desc."\r\n";

		foreach ($participants as $i => $attendee) {
			$text .= "ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN".$attendee.";X-NUM-GUESTS=0:MAILTO:".$attendee."\r\n";
		}
	$text .= "END:VEVENT\r\n".
		"END:VCALENDAR\r\n";

	$headers = "From: ".$participants[0]."\n";
	$headers = "Reply-To: ".$participants[0]."\n";
	$headers .= 'Content-Type:text/calendar; Content-Disposition: inline; charset=utf-8;\r\n';
	$headers .= "Content-Type: text/plain;charset=\"utf-8\"\r\n";

	$phpmailer->Subject = $subject;
	$phpmailer->Body = $desc;
	$phpmailer->AltBody = $text;
	$phpmailer->Ical = $text;

	if(!$phpmailer->send()) { return false; }
	return true;
}

Ich habe die Funktion gebaut, dass mir Kunden eine Einladung zusenden können an freien Terminen. Sich selbst muss man natürlich auch einladen. Die erste Mailadresse die angegeben wird, wird automatisch als Organisator verwendet:

<?php
$participants = array('test@test.ch','kunde@domain.de');
$subject = 'Betreff der Mail';
$desc = "Beschreibung der Mail";
$start_time = gmttime(); // GMT Zeit des Start
$end_time = gmttime() // GMT Zeit Ende
$location = 'Zoom oder vor Ort'
sendOutlookInvitation($participants, $subject, $desc, $start_time, $end_time, $location='');

Viel Spass damit.

Mit dem folgenden Code, werden alle Bilder auf Lazy Load bei WordPress umgestellt.

add_filter( 'wp_get_attachment_image_attributes', 'alter_att_attributes_wpse_102079', 20);
function alter_att_attributes_wpse_102079($attr) {
	if (strpos($attr['class'], 'skip-lazy') === false) {
		$attr['data-original'] = $attr['src'];
		unset($attr['src']);
		if (isset($attr['srcset'])) {
			$attr['data-original-set'] = $attr['srcset'];
			unset($attr['srcset']);
		}
		$attr['class'] .= ' lazy';
	}
	return $attr;
}

Bestellungen auf Rechnung bleiben normal immer auf “on hold” hängen. Damit diese automatisch “Processing” erhalten, muss folgender Code im Childtheme oder Plugin platziert werden:

add_action( 'woocommerce_thankyou', 'woocommerce_auto_processing_orders');
function woocommerce_auto_processing_orders( $order_id ) {
	if(!$order_id) return;
	$order = wc_get_order( $order_id );
	if($order->has_status('on-hold')) { $order->update_status( 'processing' ); }
}

Dieser Code setzt alle Bestellungen automatisch auf processing. Wenn man will, kann man auch prüfen ob die Bestellung per “bacs” gemacht wurde (Rechnung).

function debug_hook2() { echo "<p>--- Hook ---</p>";}
function debug_hook($hook) {
	global $wp_filter, $debughook;
	$debughook = $hook;
	$arr = array();
	foreach ($wp_filter[$hook]->callbacks as $nr => $ho) {
		$arr[$nr] = key($ho);
	}
	add_action($hook, 'debug_hook2',1);
	foreach ($arr as $nr => $ho) {
		add_action($hook, 'debug_hook2',$nr+1);
	}

	$out = "<pre>".print_r($arr,true)."</pre>";
	return $out;
}
echo debug_hook('woocommerce_email_order_details');
add_filter( 'avia_contact_form_args', 'no_enfold_autoresponder',80);
function no_enfold_autoresponder($form_args) {
	$form_args['autoresponder'] = false;
	$form_args['autoresponder_subject'] = '';
	$form_args['autoresponder_email'] = '';
	$form_args['autoresponder_reply_to'] = '';
	return $form_args;
}
add_filter('avf_alb_supported_post_types', 'wuk_visualeditor_for_post_types', 10, 1);
function wuk_visualeditor_for_post_types( array $supported_post_types ) {
  $supported_post_types[] = 'dein-post-type';
  return $supported_post_types;
}

Beispiel für Google Ads:

add_filter('avf_contact_form_submit_button_attr','avia_add_submit_attributes_to_cf', 10, 3);
function avia_add_submit_attributes_to_cf($att, $formID, $form_params){
	$att = "onclick=\"gtag('event', 'conversion', {'send_to': 'AW-942730802/sddUCP_7tGYQstzDwQM'});\"";
	return $att;
}

Beispiel für Linkedin:

add_filter( 'avia_contact_form_args', 'change_enfold_success_msg');
function change_enfold_success_msg($form_args, $post_id='') {
	$form_args['success'] = str_replace(
		"</h3>",
		'<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=..." /></h3>',
		$form_args['success']
	);
	return $form_args;
}
add_filter( 'wp_mail_from', function() { return 'example@example.com'; } );
add_filter( 'wp_mail_from_name', function() { return 'Example'; } );	

Schriften werden anschliessend nicht mehr von gfonts geladen.

add_filter( 'elementor/frontend/print_google_fonts', '__return_false' );
add_action('wp_enqueue_scripts', 'google_fonts_local');
function google_fonts_local() {
	wp_register_style('google_fonts_local', plugins_url('fonts/stylesheet.css',__FILE__ ));
	wp_enqueue_style('google_fonts_local');
}

Schriften müssen danach weiterhin lokal über das CSS geladen werden und muss manuell eingebaut werden!

add_filter( 'site_status_tests', 'sitehealthcheck' );
function sitehealthcheck( $tests ) {
	unset($test);
	return $tests;
}