Contact form with attachment and reCAPTCHA

The contact form sample with email attachment and Google reCAPTCHA. There are two ways to avoid bots. First, it uses the empty hidden input, and PHP will check this input is empty when bots fill it automatically. After then, it uses the wp_create_nonce and wp_verify_nonce to check the form sending is come from this site.

Thumbnail

PHPJSPugSCSS
// <head>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

<?php
$fullname = (isset($_POST['fullname']))?sanitize_text_field($_POST['fullname']):'';
$nickname = (isset($_POST['nickname']))?sanitize_text_field($_POST['nickname']):'';
$lname = (isset($_POST['lname']))?sanitize_text_field($_POST['lname']):''; 	// honey pot
$phone = (isset($_POST['phone']))?sanitize_text_field($_POST['phone']):'';
$email = (isset($_POST['email']))?sanitize_email($_POST['email']):'';
$subject = (isset($_POST['subject']))?sanitize_text_field($_POST['subject']):'';
$message = (isset($_POST['message']))?sanitize_textarea_field($_POST['message']):'';
$attach = (isset($_FILES['attach']['name']))?$_FILES['attach']['name']:'';

if( isset( $_POST['contact_form'] ) && wp_verify_nonce( $_POST['contact_form'], 'send_form' )){		// use nonce to avoid CSRF
	$sendStauts;
	if( !empty($nickname) && !empty($subject) && !empty($message) && empty($lname) ){

		// Attachment have to upload to media first.
		$post_id = $post->ID;
		if ( !empty($_FILES)  ) {
			require_once( ABSPATH . 'wp-admin/includes/admin.php' );
			$id = media_handle_upload( 'attach', $post_id );
			unset( $_FILES );
			if( is_wp_error( $id ) ) {
				$errors['upload_error'] = $id;
				$id = false;
			}
    }

		$attachments = array( get_attached_file($id) );		// Get the attachment path
		$headers = 'Content-Type: text/html; charset=UTF-8';
		$content = '<div><p>來信主旨:'.$subject.'</p><p>姓名:'.$fullname.'</p><p>暱稱:'.$nickname.'</p><p>電話:'.$phone.'</p><p>電子郵件:'.$email.'</p><p>詢問內容:'.$message.'</p></div>';
		wp_mail( get_option('admin_email'),'【'.get_the_title().'】投稿通知信', $content,$headers,$attachments );
		$sendStauts = true;
	} else {
		$sendStauts = false;
	}
}
?>

<section class="uk-margin-medium-top">
	<div class="uk-container">
		<h1 class="uk-text-primary heading-small text-bold heading-underline uk-margin-medium-bottom" style="line-height:1;"><span><?php echo esc_html(get_the_title()); ?></span></h1>
		<div class="uk-width-2-3@m">
			<?php if(isset($sendStauts)): ?>
				<?php if($sendStauts): ?>
				<div class="uk-alert-success" uk-alert>
					<a class="uk-alert-close" uk-close></a>
					<p>投稿成功,感謝您的來信,我們會由專人協助您投稿!</p>
				</div>
				<?php else: ?>
					<div class="uk-alert-danger" uk-alert>
					<a class="uk-alert-close" uk-close></a>
					<p>投稿失敗,請確認欄位是否已填寫正確!</p>
				</div>
				<?php endif; ?>
			<?php endif; ?>
			<h2 class="text-medium uk-margin-medium-bottom uk-text-primary">請填寫以下資料<span class="text-red text-xsmall uk-margin-small-left">( * 請務必填寫完整)</span></h2>
			<form method="post" action="<?php echo esc_url(get_the_permalink()); ?>" enctype="multipart/form-data">
				<div class="uk-margin-medium-bottom uk-child-width-1-2@s" uk-grid>
					<div>
						<label class="text-medium uk-display-block uk-margin-small-bottom">&nbsp;姓名<span class="text-small text-gray">&nbsp;</span></label>
						<input class="uk-border-rounded uk-input background" name="fullname" type="text" style="height: 54px;" maxlength="20" placeholder="王小明" value="<?php echo esc_attr($fullname); ?>">
					</div>
					<div class="uk-hidden">
						<label class="text-medium uk-display-block uk-margin-small-bottom">&nbsp;姓名<span class="text-small text-gray">&nbsp;</span></label>
						<input class="uk-border-rounded uk-input background" name="lname" type="text" style="height: 54px;" maxlength="20" placeholder="王小明">
					</div>
					<div>
						<label class="text-medium uk-display-block uk-margin-small-bottom"><span class="text-red">*</span>&nbsp;暱稱</label>
						<input class="uk-border-rounded uk-input background" name="nickname" type="text" style="height: 54px;" maxlength="20" required placeholder="小明" value="<?php echo esc_attr($nickname); ?>">
					</div>
				</div>
				<div class="uk-margin-medium-bottom uk-child-width-1-2@s" uk-grid>
					<div>
						<label class="text-medium uk-display-block uk-margin-small-bottom">&nbsp;電話<span class="text-small text-gray">&nbsp;</span></label>
						<input class="uk-border-rounded uk-input background" name="phone" type="text" style="height: 54px;" maxlength="20" placeholder="0966-xxx-xxx" value="<?php echo esc_attr($phone); ?>">
					</div>
					<div>
						<label class="text-medium uk-display-block uk-margin-small-bottom">&nbsp; E-mail<span class="text-small text-gray">&nbsp;</span></label>
						<input class="uk-border-rounded uk-input background" name="email" type="email" style="height: 54px;" maxlength="100" placeholder="email@mail.com" value="<?php echo esc_attr($email); ?>">
					</div>
				</div>
				<div class="uk-margin-medium-bottom">
					<label class="text-medium uk-display-block uk-margin-small-bottom"><span class="text-red">*</span>&nbsp;信件主旨</label>
					<input class="uk-border-rounded uk-input background" name="subject" type="text" style="height: 54px;" maxlength="100" required value="<?php echo esc_attr($subject); ?>">
				</div>
				<div class="uk-margin-medium-bottom">
					<label class="text-medium uk-display-block uk-margin-small-bottom"><span class="text-red">*</span>&nbsp; 信件內容</label>
					<textarea class="uk-border-rounded uk-textarea background" name="message" rows="10" required></textarea>
				</div>
				<div class="uk-margin-large-bottom">
					<label class="text-medium uk-display-block uk-margin-small-bottom">&nbsp; 附加檔案(格式 : .jpg .png .txt .doc .xls,容量小於 20MB)</label>
					<div class="uk-margin">
						<div uk-form-custom="target: true">
							<input id="attach" type="file" accept=".jpg,.png,.txt,.doc,.xls" name="attach">
							<input class="uk-input uk-form-width-medium uk-border-rounded" type="text" placeholder="選擇檔案" disabled="" style="height: 54px;">
							<button class="uk-button uk-button-primary uk-border-rounded text-medium" style="height: 54px;">瀏覽</button>
						</div>
					</div>
				</div>
				<div class="uk-margin-auto-left uk-margin-auto-right uk-margin-large-bottom" style="width: 320px;">
					<!-- <reCAPTCHA>-->
					<div class="uk-margin-auto-left uk-margin-auto-right uk-margin-medium-bottom g-recaptcha" style="width: 304px" data-sitekey="6LeqxdgUAAAAAFOIpdA9lFLdownnGnfrMORxwW97"></div>
					<!-- </reCAPTCHA>-->
					<div class="uk-child-width-1-2 uk-grid-small" uk-grid>
						<div>
							<button class="uk-width-1-1 text-medium uk-button uk-button-default uk-border-rounded" type="reset" style="height: 54px;">重填</button>
						</div>
						<div>
							<button class="uk-width-1-1 text-medium uk-button uk-button-primary uk-border-rounded" type="submit" style="height: 54px;">送出</button>
						</div>
					</div>
				</div>
				<?php wp_nonce_field( 'send_form', 'contact_form' ); ?>
			</form>
		</div>
	</div>
</section>
// check the attachment file size
if (vars.attach !== null){
  vars.attach.addEventListener('change',e=>{
    if (e.currentTarget.files[0].size > 20971520){
      alert('附件容量不得超過 20MB');
      e.currentTarget.value =''
    }
  })
}
div(class='uk-width-2-3@m')
  h2.text-medium.uk-margin-medium-bottom.uk-text-primary
    | 請填寫以下資料
    span.text-red.text-xsmall.uk-margin-small-left ( * 請務必填寫完整)
  form(method='post' action='/')
    .uk-margin-medium-bottom(uk-grid class='uk-child-width-1-2@s')
      div
        label.text-medium.uk-display-block.uk-margin-small-bottom
          | &nbsp;姓名
          span.text-small.text-gray &nbsp;(不會公開)
        input.uk-border-rounded.uk-input.background(name='lastname' type='text' style='height: 54px;' max='20' placeholder='王小明')
      div
        label.text-medium.uk-display-block.uk-margin-small-bottom
          span.text-red *
          | &nbsp;暱稱
        input.uk-border-rounded.uk-input.background(name='nickname' type='text' style='height: 54px;' max='20' required placeholder='小明')
    .uk-margin-medium-bottom(uk-grid class='uk-child-width-1-2@s')
      div
        label.text-medium.uk-display-block.uk-margin-small-bottom
          | &nbsp;電話
          span.text-small.text-gray &nbsp;(不會公開)
        input.uk-border-rounded.uk-input.background(name='phone' type='text' style='height: 54px;' max='20' placeholder='0966-xxx-xxx')
      div
        label.text-medium.uk-display-block.uk-margin-small-bottom
          | &nbsp; E-mail
          span.text-small.text-gray &nbsp;(不會公開)
        input.uk-border-rounded.uk-input.background(name='email' type='email' style='height: 54px;' max='100' placeholder='mail@msil.com')
    .uk-margin-medium-bottom
      label.text-medium.uk-display-block.uk-margin-small-bottom
        span.text-red *
        | &nbsp;信件主旨
      input.uk-border-rounded.uk-input.background(name='subject' type='text' style='height: 54px;' max='100' required)
    .uk-margin-medium-bottom
      label.text-medium.uk-display-block.uk-margin-small-bottom
        span.text-red *
        | &nbsp; 信件內容
      textarea.uk-border-rounded.uk-textarea.background(name='message' rows='10' required)
    .uk-margin-large-bottom
      label.text-medium.uk-display-block.uk-margin-small-bottom
        | &nbsp; 附加檔案(格式 : .jpg .png .txt .doc .xls,容量小於 20MB)
      .uk-margin
        div(uk-form-custom="target: true")
          input#attach(type="file" accept=".jpg,.png,.txt,.doc,.xls" name='attach')
          input.uk-input.uk-form-width-medium.uk-border-rounded(type="text" placeholder="選擇檔案" disabled="" style='height: 54px;')
          button.uk-button.uk-button-primary.uk-border-rounded.text-medium(style='height: 54px;') 瀏覽
    .uk-margin-auto-left.uk-margin-auto-right.uk-margin-large-bottom(style='width: 320px;')
      // <reCAPTCHA>
      .uk-margin-auto-left.uk-margin-auto-right.uk-margin-medium-bottom(style='width: 304px' class="g-recaptcha" data-sitekey="6LeqxdgUAAAAAFOIpdA9lFLdownnGnfrMORxwW97")
      // </reCAPTCHA>
      .uk-child-width-1-2.uk-grid-small(uk-grid)
        div
          button.uk-width-1-1.text-medium.uk-button.uk-button-default.uk-border-rounded(type='reset' style='height: 54px;') 重填
        div
          button.uk-width-1-1.text-medium.uk-button.uk-button-primary.uk-border-rounded(type='submit' style='height: 54px;') 送出
.uk-input,
.uk-textarea {
  &.background {
    padding-left: 15px;
    background-color: #f5f6f6;
    &:focus {
      border: 1px solid $global-primary-background;
      background-color: #fff;
    }
  }
}