Wordpress 无需插件即可将包含多个文件的表单发送到电子邮件
Wordpress send form with multiple files to email without plugin
目的是让用户将自己的material新文章(文本和文件)发送到管理员的邮箱。
有一个表格:
<form class="form form-send" enctype="multipart/form-data">
<div class="send__inputs-block">
<div class="sliding-label__block send__textarea-block">
<textarea name="comment" id="comment" class="input textarea send__textarea" placeholder=" "></textarea>
<label for="comment" class="text text--fz-18 sliding-label">
<?php echo get_post_meta( get_the_ID(), 'joint_send_comment_text', true ); ?>
</label>
</div>
<div class="sliding-label__block">
<input id="name" type="text" name="name" class="input input-text" placeholder=" ">
<label for="name" class="text text--fz-18 sliding-label">
<?php echo get_post_meta( get_the_ID(), 'joint_send_name_text', true ); ?>
</label>
</div>
</div>
<div class="send__file-block">
<input id="file" type="file" name="file" class="input-file" multiple>
<label for="file" class="label label-file">
<i class="joint-upload icon"></i>
<span class="text text--fz-14 upload__text">
<?php echo get_post_meta( get_the_ID(), 'joint_send_file_text', true ); ?>
</span>
</label>
</div>
<button type="submit" class="button form-button">
<span class="button-text">
<?php echo get_post_meta( get_the_ID(), 'joint_send_submit_text', true ); ?>
</span>
</button>
</form>
这是JS代码:
function formSend(e, form) {
e.preventDefault()
if (formValidate(form)) return
let backFile = jointAjax.ajaxurl
let curPage = ''
let formData = new FormData(form)
if (form.classList.contains('form-contacts')) {
curPage = 'contacts'
}
else if (form.classList.contains('form-send')){
curPage = 'send'
let uploadFiles = []
for (let single of form.file.files) {
uploadFiles.push(single)
}
console.log(uploadFiles[0])
formData.append('file', uploadFiles)
}
else {
return
}
formData.append('action', curPage)
fetch(backFile, {
method: 'POST',
body: formData,
})
.then(form.reset())
.catch(error => {
error.json().then(response => {
alert(response.message)
})
})
}
这是 PHP 代码:
add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
global $joint_settings;
$data = json_encode($_POST);
$data = json_decode($data, true);
$attachment = array();
if (isset($_FILES['file'])) {
foreach($_FILES['file'] as $key => $file) {
$attachment[] = $file['tmp_name'] . $file['name'];
}
}
$mailBody = '';
foreach ($data as $key => $value) {
if ($key === 'action' || $key === 'file') continue;
if (!empty($data[$key]))
$mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
}
$headers = array(
'From: Joint Admin <' . SMTP_FROM . '>',
'content-type: text/html'
);
wp_mail(
$joint_settings['send_mail_to'],
$joint_settings['send_mail_theme'],
$mailBody,
$headers,
WP_CONTENT_DIR . '\' . $_FILES['file']['name']
);
// wp_send_json_success($_FILES['file']['tmp_name'] . '\' . $_FILES['file']['name']);
}
我已经查看了各种论坛、文章和视频,但我似乎无法完成任务。
在wp_mail中我们必须传递文件的完整路径,但是我们从哪里得到那个路径呢?
而且无论我如何尝试处理多个文件,函数 returns 仅回复最后一个文件的名称。
SMTP 设置正确。收到电子邮件,但没有文件。
请帮忙 - 我不知道该怎么办了。
我明白了 - 我查看了 Contact form 7 插件中的实现并理解了其中的原理。
基本思路是先将上传的文件移动到网站的内部目录,然后从那里发送到邮箱。
在JS中我只改变了一件事(你可以发送文件到请求而不处理):
else if (form.classList.contains('form-send')){
formData.append('file', form.file.files)
curPage = 'send'
}
我的处理函数看起来像这样:
add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
global $joint_settings;
$data = json_encode($_POST);
$data = json_decode($data, true);
$mailBody = '';
foreach ($data as $key => $value) {
if ($key === 'action' || $key === 'file') continue;
if (!empty($data[$key]))
$mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
}
$headers = array(
'From: Joint Admin <' . SMTP_FROM . '>',
'content-type: text/html'
);
$file = $_FILES['file'];
// joint_array_flatten() - converts multi-dimensional array to a flat array
$names = joint_array_flatten( $file['name'] );
$tmp_names = joint_array_flatten( $file['tmp_name'] );
$uploads = wp_get_upload_dir()['basedir'];
$uploads_dir = path_join( $uploads, 'joint_uploads' );
$uploaded_files = array();
foreach ( $names as $key => $filename ) {
$tmp_name = $tmp_names[$key];
if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
continue;
}
// joint_antiscript_file_name() - converts a file name to one that is not executable as a script
$filename = joint_antiscript_file_name( $filename );
$filename = wp_unique_filename( $uploads_dir, $filename );
$new_file = path_join( $uploads_dir, $filename );
if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
wp_send_json_error( json_encode( array('message' => 'Upload error') ) );
return;
}
// Make sure the uploaded file is only readable for the owner process
chmod( $new_file, 0400 );
$uploaded_files[] = $new_file;
}
wp_mail(
$joint_settings['send_mail_to'],
$joint_settings['send_mail_theme'],
$mailBody,
$headers,
$uploaded_files
);
// Deletes sent files as they are on the email
foreach ( $uploaded_files as $filepath ) {
wp_delete_file( $filepath );
}
}
我从 Contact form 7 中窃取了几个功能。反脚本绝对有用,但是否需要 joint_array_flatten - 我不知道,但我已经累得想不起来了更多
最后我从目录中删除了下载的文件,这样它就不会被阻塞。
此外,正如用户@TangentiallyPerpendicular 正确指出的那样,您需要将 [] 添加到 file-input 名称才能发送多个文件:
<input id="file" type="file" name="file[]" class="input-file" multiple>
否则,就是这样。我希望有一天这会帮助其他人,他们不必像我一样为类似的任务而苦恼)
目的是让用户将自己的material新文章(文本和文件)发送到管理员的邮箱。
有一个表格:
<form class="form form-send" enctype="multipart/form-data">
<div class="send__inputs-block">
<div class="sliding-label__block send__textarea-block">
<textarea name="comment" id="comment" class="input textarea send__textarea" placeholder=" "></textarea>
<label for="comment" class="text text--fz-18 sliding-label">
<?php echo get_post_meta( get_the_ID(), 'joint_send_comment_text', true ); ?>
</label>
</div>
<div class="sliding-label__block">
<input id="name" type="text" name="name" class="input input-text" placeholder=" ">
<label for="name" class="text text--fz-18 sliding-label">
<?php echo get_post_meta( get_the_ID(), 'joint_send_name_text', true ); ?>
</label>
</div>
</div>
<div class="send__file-block">
<input id="file" type="file" name="file" class="input-file" multiple>
<label for="file" class="label label-file">
<i class="joint-upload icon"></i>
<span class="text text--fz-14 upload__text">
<?php echo get_post_meta( get_the_ID(), 'joint_send_file_text', true ); ?>
</span>
</label>
</div>
<button type="submit" class="button form-button">
<span class="button-text">
<?php echo get_post_meta( get_the_ID(), 'joint_send_submit_text', true ); ?>
</span>
</button>
</form>
这是JS代码:
function formSend(e, form) {
e.preventDefault()
if (formValidate(form)) return
let backFile = jointAjax.ajaxurl
let curPage = ''
let formData = new FormData(form)
if (form.classList.contains('form-contacts')) {
curPage = 'contacts'
}
else if (form.classList.contains('form-send')){
curPage = 'send'
let uploadFiles = []
for (let single of form.file.files) {
uploadFiles.push(single)
}
console.log(uploadFiles[0])
formData.append('file', uploadFiles)
}
else {
return
}
formData.append('action', curPage)
fetch(backFile, {
method: 'POST',
body: formData,
})
.then(form.reset())
.catch(error => {
error.json().then(response => {
alert(response.message)
})
})
}
这是 PHP 代码:
add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
global $joint_settings;
$data = json_encode($_POST);
$data = json_decode($data, true);
$attachment = array();
if (isset($_FILES['file'])) {
foreach($_FILES['file'] as $key => $file) {
$attachment[] = $file['tmp_name'] . $file['name'];
}
}
$mailBody = '';
foreach ($data as $key => $value) {
if ($key === 'action' || $key === 'file') continue;
if (!empty($data[$key]))
$mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
}
$headers = array(
'From: Joint Admin <' . SMTP_FROM . '>',
'content-type: text/html'
);
wp_mail(
$joint_settings['send_mail_to'],
$joint_settings['send_mail_theme'],
$mailBody,
$headers,
WP_CONTENT_DIR . '\' . $_FILES['file']['name']
);
// wp_send_json_success($_FILES['file']['tmp_name'] . '\' . $_FILES['file']['name']);
}
我已经查看了各种论坛、文章和视频,但我似乎无法完成任务。
在wp_mail中我们必须传递文件的完整路径,但是我们从哪里得到那个路径呢? 而且无论我如何尝试处理多个文件,函数 returns 仅回复最后一个文件的名称。
SMTP 设置正确。收到电子邮件,但没有文件。
请帮忙 - 我不知道该怎么办了。
我明白了 - 我查看了 Contact form 7 插件中的实现并理解了其中的原理。
基本思路是先将上传的文件移动到网站的内部目录,然后从那里发送到邮箱。
在JS中我只改变了一件事(你可以发送文件到请求而不处理):
else if (form.classList.contains('form-send')){
formData.append('file', form.file.files)
curPage = 'send'
}
我的处理函数看起来像这样:
add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
global $joint_settings;
$data = json_encode($_POST);
$data = json_decode($data, true);
$mailBody = '';
foreach ($data as $key => $value) {
if ($key === 'action' || $key === 'file') continue;
if (!empty($data[$key]))
$mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
}
$headers = array(
'From: Joint Admin <' . SMTP_FROM . '>',
'content-type: text/html'
);
$file = $_FILES['file'];
// joint_array_flatten() - converts multi-dimensional array to a flat array
$names = joint_array_flatten( $file['name'] );
$tmp_names = joint_array_flatten( $file['tmp_name'] );
$uploads = wp_get_upload_dir()['basedir'];
$uploads_dir = path_join( $uploads, 'joint_uploads' );
$uploaded_files = array();
foreach ( $names as $key => $filename ) {
$tmp_name = $tmp_names[$key];
if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
continue;
}
// joint_antiscript_file_name() - converts a file name to one that is not executable as a script
$filename = joint_antiscript_file_name( $filename );
$filename = wp_unique_filename( $uploads_dir, $filename );
$new_file = path_join( $uploads_dir, $filename );
if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
wp_send_json_error( json_encode( array('message' => 'Upload error') ) );
return;
}
// Make sure the uploaded file is only readable for the owner process
chmod( $new_file, 0400 );
$uploaded_files[] = $new_file;
}
wp_mail(
$joint_settings['send_mail_to'],
$joint_settings['send_mail_theme'],
$mailBody,
$headers,
$uploaded_files
);
// Deletes sent files as they are on the email
foreach ( $uploaded_files as $filepath ) {
wp_delete_file( $filepath );
}
}
我从 Contact form 7 中窃取了几个功能。反脚本绝对有用,但是否需要 joint_array_flatten - 我不知道,但我已经累得想不起来了更多
最后我从目录中删除了下载的文件,这样它就不会被阻塞。
此外,正如用户@TangentiallyPerpendicular 正确指出的那样,您需要将 [] 添加到 file-input 名称才能发送多个文件:
<input id="file" type="file" name="file[]" class="input-file" multiple>
否则,就是这样。我希望有一天这会帮助其他人,他们不必像我一样为类似的任务而苦恼)