I have a contact form 7 form where a user can input his/her e-mail address and a coupon code. If the e-mail-address or code cannot be found in the database, distinct error messages should be displayed to the user after the submit.
I use the wpcf7_before_send_mail hook to find out if the e-mail address / coupon code are valid:
add_action('wpcf7_before_send_mail', 'your_wpcf7_mail_sent_function');
function your_wpcf7_mail_sent_function($contact_form)
{
//get user e-mail and coupon nr from database
$entry = select("SELECT e-mail, coupon_nr FROM {$wpdb->prefix} woocommerce_coupons WHERE coupon_nr = '{$couponNr}'");
if (is_null($entry[0]->e-mail)
{
$skipMail = true;
$status = "USER_NOT_FOUND";
}
else if(is_null($entry[0]->coupon_nr)
{
$skipMail = true;
$status = "COUPON_INVALID";
}
else
{
$status = "OK";
}
}
What I want to achieve is to display an appropriate error message to the user depending on the status. E.g. if status is "USER_NOT_FOUND", a different message should be displayed as if the status was "COUPON_INVALID".
Any help is very appreciated.
Related
I have a form for subscription. And I want to limit the number of submits by IP, for example, 3 times a day? How can I do it with hooks?
Use the WordPress do_shortcode_tag filter introduced in v4.7, which get fired when a shortcode is rendered. You can then replace the rendered CF7 form with a notification for users who have reached their submitted limit
add_filter('do_shortcode_tag', 'restrict_my_form',10,3);
function restrict_my_form($output, $tag, $attrs){
//check if this is your form being rendered.
if($tag=='contact-form-7' and $attrs['id'] == 1){
//get the IP address of the submission as $ip_address
$cannot_submit = get_transient('form_submission_from_'.$ip_address);
if($cannot_submit !== false){
$cannot_submit = explode('|',$cannot_submit);
if($cannot_submit[0] > 2){ //already submitted 3 times.
$cannot_submit = true;
}else{ //can still submit.
$cannot_submit = false;
}
}//else this is the first submit or transient expired.
if($cannot_submit){
//replace the html for with your notification.
$output ='<p>You have reached the limit of submissions</p>';
}
}
return $output;
}
To verify the IP of the user, the question has already been answered here.
You will also need to track users' submissions per IP, I suggest you store these as transients for 24 hours, this way they will automatically disappear after a day. Something along these lines (I haven't tested this code, so let me know if you're not getting the expected results.)
add_action('wpcf7_mail_sent', function($form){
//get the IP address of the submission as $ip_address
$time = current_time('timestamp');
$expiry = DAY_IN_SECONDS; //24 hours.
$value = 1;
$last_value = get_transient('form_submission_from_'.$ip_address);
if($last_value !== false){
$last_value = explode('|',$last_value);
$expiry = DAY_IN_SECONDS - ($time - $last_value[1]); //remaining time since first submission.
$time = $last_value[1]; //keep time of first submission.
$value = ($last_value[0]+1);
delete_transient('form_submission_from_'.$ip_address);
}
$value = "$value|$time";
set_transient('form_submission_from_'.$ip_address, $value, $expiry);
});
Good day!
I’m using Contact Form 7 and its wpcf7_before_send_mail action to interact with an API before sending the email. If the API returns an error, I want to be able to grab that error, display it as an error and prevent the form from being submitted.
I can’t seem to find what I’m looking for anywhere online. The best I can do is use the mail_sent_ok message string and display the error within it (which is obviously not the solution).
Basically, the ultimate solution would be to force the form submission to fail.
Anyone else in the same boat?
I'm not sure if it was possible at the time you asked your question but the wpcf7_before_send_mail hook has an abort flag that your just have to set to avoid mail to be sent.
for instance in pseudo PHP
add_action('wpcf7_before_send_mail', 'your_function', 10, 3);
function your_function($form, &$abort, $object){
$error = 1;
if($error != 0) {
$abort = true;
$object->set_response("An error happened");
}
}
Based on Louise-Philippe's answer, I solved with this code, since $object parameter happends to be always null:
add_action('wpcf7_before_send_mail', 'your_function', 10, 3);
function your_function($form, &$abort, $object){
$error = 1;
if($error != 0) {
$abort = true;
$msgs = $form->prop('messages');
$msgs['mail_sent_ng'] = "An error happened"; //<- your custom error message
$form->set_properties(array('messages' => $msgs));
}
}
Note: it's not mail_sent_ok but mail_sent_ng so you can have red border as predefined error messages.
you can do a custom validation with this filter :
add_filter("wpcf7_validate", function ($result, $tags) {
$valid = FALSE; // here you can do your API call to calculate the validation
if (!$valid) {
$result->offsetSet(
"reason"
, ["your-name" => "error message for this field"]
);
}
return $result;
}, 10, 2);
your-name must be the name of a existing field of this form.
I'm making an integration of Shopp and Mailchimp for a client on a WordPress-based site. The checkout page has input for multiple email addresses, all of which should be added to MailChimp via the API. I've had success with listSubscribe() using the MCAPI.php wrapper in getting the first email to work. Can the listSubscribe() be re-used in the same PHP function that runs as checkout is processed?
Here's the code I have at the moment:
/* include MailChimp API on checkout init */
add_action('shopp_order_success', 'opc_mc_checkout');
function opc_mc_checkout () {
// do stuff
require_once 'MCAPI.class.php';
$apikey='redacted'; // Enter your API key
$api = new MCAPI($apikey);
$retval = $api->lists();
$listid='redacted'; // Enter list Id here
$email=shopp('purchase.email', 'return=true'); // Enter subscriber email address
$name=shopp('purchase.firstname', 'return=true'); // Enter subscriber first name
$lname=shopp('purchase.lastname', 'return=true'); // Enter subscriber last name
// By default this sends a confirmation email - you will not see new members
// until the link contained in it is clicked!
$merge_vars = array('FNAME' => $name, 'LNAME' => $lname);
if($api->listSubscribe($listid, $email,$merge_vars) === true) {
}
/* teacher extra emails */
$apikey='redacted'; // Enter your API key
$api = new MCAPI($apikey);
$retval = $api->lists();
$listid='redacted'; // Enter list Id here
$teacher_1_email=shopp('purchase.data', 'name=Teacher 1 Email&return=true'); // Enter subscriber email //$teacher_1_email=$_POST['Teacher 1 Email']; // Enter subscriber email
$teacher_1_name=shopp('purchase.firstname', 'return=true'); // Enter subscriber first name
$teacher_1_lname=shopp('purchase.lastname', 'return=true'); // Enter subscriber last name
$merge_vars = array('FNAME' => $teacher_1_name, 'LNAME' => $teacher_1_lname);
if($api->listSubscribe($listid, $teacher_1_email,$merge_vars) === true) {
}
I've searched Google and the API documentation up and down without luck. Ay help would be greatly appreciated!
Thanks!
WooCommerce -> Settings -> EmailS -> the first two options, "FROM: Name, FROM: Email", are the Sender's email and name. When an order is placed a notification email is sent to both Shop Manager and Customer from the same Sender's email and name (which we set from admin dashboard).
When Customer replies to that email, he basically replies to Shop Manager and it works fine.
But Shop Manager receives the notification email from his (given) email address, in actually there would be client's email.
P.S: I want that Shop Manager gets the email from the customer's billing email and customer gets it from Shop Manager's given email.
https://wordpress.org/plugins/woocommerce/
The only way I can think of to achieve this is to programmatically generate the Shop Manager notification email using one of the system action hooks. Since there is only one field in the "from" settings, it will be used (by default) for all the outbound messages.
That said, check out the Code Snippets plugin at https://wordpress.org/plugins/code-snippets/. You can put some code here (and it will be saved to the DB, and included the system code at runtime) that could generate this programmatic email when, say, a new order is generated.
Hope it helps.
After going through your question it made sense that for a shop owner it needs to be like the mail should have sent from address as the client's email address, so that he can reply to each order in a single email thread.
//filter for the "mail from" email address which is set in WooCommerce Settings Email Tab-> Email Sender Options -> "From" Email Address which is generally set to the shop admin email address or a support team email address.
add_filter('wp_mail_from', 'wdm_sent_from_email', 99, 1);
//function which will change the mail from email address to the the Customer's billing address if the mail this filter is running which sending mail to the admin.
function wdm_sent_from_email( $sent_from = '' ) {
//check whether our custom parameter is set or not.
if ( isset($_POST['wdm_sent_to_admin']) ) {
//check whether the mail is sent to the admin and other recieptent other than customer
if ( $_POST['wdm_sent_to_admin'] ) {
//set it to the customer's billing email
$sent_from = $_POST['billing_email'];
//set this parameter back to false
$_POST['wdm_sent_to_admin'] == false;
}
}
return $sent_from;
}
//filter for email from name
add_filter('wp_mail_from_name', 'wdm_sent_from_name', 99, 1);
function wdm_sent_from_name( $sent_from_name = '' ) {
//check whether our custom parameter is set or not.
if ( isset($_POST['wdm_sent_to_admin_from_name']) ) {
//check whether the mail is sent to the admin and other recieptent other than customer
if ( $_POST['wdm_sent_to_admin_from_name'] ) {
//set sent mail from name eg. "Website-Name customer"
$sent_from_name = wp_specialchars_decode(esc_html(get_option('woocommerce_email_from_name')), ENT_QUOTES) . " customer";
//set this parameter back to false
$_POST['wdm_sent_to_admin_from_name'] = false;
}
}
return $sent_from_name;
}
//action were we will set and the parameter to indicate whether the mail is sent to admin or customers.
add_action('woocommerce_email_header', 'wdm_header_function', 99, 1);
function wdm_header_function( $email_heading ) {
if ( $email_heading == 'New customer order' ) {
//parameter to indicate whether to change the from email in the mail.
$_POST['wdm_sent_to_admin'] = true;
//parameter to indicate whether to change the from name in the mail.
$_POST['wdm_sent_to_admin_from_name'] = true;
//Just to indicate in mail sent to admin that the sent from email is set in code.
echo "<b>Its Because you have chosen to have this email sent from Customer's Email id.</b>";
} else {
//parameter to indicate whether to change the from email in the mail.
$_POST['wdm_sent_to_admin'] = false;
//parameter to indicate whether to change the from name in the mail.
$_POST['wdm_sent_to_admin_from_name'] = false;
}
}
Note : This might give you and alert message while viewing the message at your side only saying "This message may not have been sent by: (your customer's billing address) " as this is not really sent by a customer to you.
Try out the above code and lemme know whether it works for you and accomplishes your purpose.
I think you can also use wordpress hooks for that:
// Function to change email address
function wpb_sender_email( $original_email_address ) {
return 'tim.smith#example.com';
}
// Function to change sender name
function wpb_sender_name( $original_email_from ) {
return 'Tim Smith';
}
// Hooking up our functions to WordPress filters
add_filter( 'wp_mail_from', 'wpb_sender_email' );
add_filter( 'wp_mail_from_name', 'wpb_sender_name' );
I’m just after some coding help with a Woocommerce tweak a client needs on their Wordpress site. We have a Woocommerce site that has just been set up as an enquiry system. When the customer places an order, the client gets a normal New Order notification by email.
However, we need the format of that email to be modified so that when the client get that email, they can reply to their customer's email address, not their own site's email address that was set in Woocommerce. (As it is normally, they would have to either forward it or copy/paste the contents of that email into a fresh email and put in the customers email address manually in order to respond.) They don’t want to have to do that.
How can I achieve this
many thanks in advance!
cheers,
Kurt
I had the same problem and managed to get this done by following this two tutorials:
http://www.skyverge.com/blog/how-to-add-a-custom-woocommerce-email/
http://web.peterhartree.co.uk/2014/woocommerce-change-reply-field/
Hopefully this helps.
Regards, Christian
The following snippet will only you to update the reply-to header for the New Order email:
add_filter('woocommerce_email_header', 'spigot_reply_to_mail_filter', 11, 3);
function spigot_reply_to_mail_filter($headers = '', $ordertype = 'new_order', $order = '') {
if(!is_object($order) || empty($order) || $ordertype !== 'new_order') { return $headers; }
$name = $order->get_billing_first_name().' '.$order->get_billing_last_name();
$email = $order->get_billing_email();
if(is_array($headers)) {
$headers['Reply-To'] = "{$name} <{$email}>";
} else {
$headers .= "Reply-To: {$name} <{$email}>\r\n";
}
return $headers;
}
credit goes to: https://spigotdesign.com/change-woocommerce-new-order-reply-address-customer/