連絡メール
このコミットが含まれているのは:
コミット
3652a4f11a
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Home;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Mail\ContactNotifyMail;
|
||||
|
||||
class Contact {
|
||||
private $field;
|
||||
|
||||
public function __construct () {
|
||||
$this->field = [
|
||||
'kenmei' => '',
|
||||
'adr' => '',
|
||||
'cat' => '',
|
||||
'cats' => [
|
||||
'' => '',
|
||||
'bugreport' => 'バグ報告したい',
|
||||
'chat' => 'チャットサービス(XMPP、IRC、Mumble)について聞きたい',
|
||||
'social' => 'SNSサービス(Pleroma、PeerTube)について聞きたい',
|
||||
'privfront' => '代替SNSフロントサービス(Nitter、Invidious、Librarian、Searx)について聞きたい',
|
||||
'storage' => 'ストレージサービス(Gitea、Nextcloud)について聞きたい',
|
||||
'otherserv' => '076外サービス(テク諏訪、076萌、URLoli、some.very.questionable.website、hozon.site、xmr.jp等)について聞きたい',
|
||||
'scam1' => 'DMCA報告したい',
|
||||
'scam2' => '営業したい',
|
||||
'scam3' => '法律について',
|
||||
'scam4' => '税金について',
|
||||
'scam5' => '無駄な話',
|
||||
],
|
||||
'bunsyo' => '',
|
||||
'gpg' => '',
|
||||
'ruleapply' => false,
|
||||
];
|
||||
}
|
||||
|
||||
public function index (Request $r) {
|
||||
if (isset($r->submit)) return $this->send($r);
|
||||
return view('pages.site.contact', ['field' => $this->field, 'err' => []]);
|
||||
}
|
||||
|
||||
public function seiko () {
|
||||
return view('pages.site.contact-seiko', ['field' => $this->field, 'suc' => ['メールを送りました!', '送信者様は連絡ルールを守ったら、24時間以内で返事します。']]);
|
||||
}
|
||||
|
||||
public function send (Request $r) {
|
||||
$this->field['adr'] = $r->adr;
|
||||
$this->field['kenmei'] = $r->kenmei;
|
||||
$this->field['cat'] = $r->cat;
|
||||
$this->field['gpg'] = !isset($r->gpg) || is_null($r->gpg) || $r->gpg == '' ? null : file_get_contents($r->file('gpg'));
|
||||
$this->field['bunsyo'] = $r->bunsyo;
|
||||
$this->field['ruleapply'] = isset($r->ruleapply);
|
||||
|
||||
$err = [];
|
||||
$gpg = null;
|
||||
|
||||
// メールアドレス
|
||||
if (!isset($this->field['adr']) || is_null($this->field['adr']) || $this->field['adr'] == '') $err[] = 'メールアドレスをご入力下さい。';
|
||||
else if (!filter_var($this->field['adr'], FILTER_VALIDATE_EMAIL)) $err[] = 'メールアドレスを正しくご入力下さい。';
|
||||
$filename = trim($this->field['adr']).'.key';
|
||||
|
||||
// 件名
|
||||
if (!isset($this->field['kenmei']) || is_null($this->field['kenmei']) || $this->field['kenmei'] == '') $err[] = '件名をご入力下さい。';
|
||||
if (str_contains($this->field['kenmei'], 'http://') || str_contains($this->field['kenmei'], 'https://')) $err[] = '件名でURLを入らないで下さい。';
|
||||
$this->field['bunsyo'] = trim($this->field['bunsyo']);
|
||||
|
||||
// カテゴリ
|
||||
if (!isset($this->field['cat']) || is_null($this->field['cat']) || $this->field['cat'] == '') $err[] = 'カテゴリをご選択下さい。';
|
||||
|
||||
// GPG
|
||||
if (!isset($this->field['gpg']) || is_null($this->field['gpg']) || $this->field['gpg'] == '') $err[] = 'GPGをご選択下さい。';
|
||||
else {
|
||||
$gpg = new \gnupg();
|
||||
$info = $gpg->import($this->field['gpg']);
|
||||
$gpg->addencryptkey($info['fingerprint']);
|
||||
Storage::disk('public')->put($filename, $this->field['gpg']);
|
||||
$path = Storage::disk('public')->path($filename);
|
||||
$verifygpg = explode("\n", $this->run('gpg --dry-run --import '.$path))[0];
|
||||
if (!str_contains($verifygpg, '処理数の合計: 1')) $err[] = $verifygpg;
|
||||
}
|
||||
|
||||
// 文章
|
||||
if (!isset($this->field['bunsyo']) || is_null($this->field['bunsyo']) || $this->field['bunsyo'] == '') $err[] = '文章をご入力下さい。';
|
||||
if (str_contains($this->field['bunsyo'], 'http://') || str_contains($this->field['bunsyo'], 'https://')) $err[] = '文章でURLを入らないで下さい。';
|
||||
$this->field['bunsyo'] = $gpg->encrypt(trim($this->field['bunsyo']));
|
||||
|
||||
// 連絡ルール
|
||||
if (!$this->field['ruleapply']) $err[] = 'ルールを同意して下さい。';
|
||||
|
||||
if (!empty($err)) {
|
||||
if (isset($this->field['gpg']) && !is_null($this->field['gpg']) && $this->field['gpg'] != '') Storage::disk('public')->delete($filename);
|
||||
return view('pages.site.contact', ['field' => $this->field, 'err' => $err]);
|
||||
}
|
||||
|
||||
// カテゴリはDMCA報告、営業、税金、法律、又は無駄な話を選択したら、いつでも送信せず失敗します。
|
||||
if (str_contains($this->field['cat'], 'scam')) {
|
||||
Storage::disk('public')->delete($filename);
|
||||
return view('pages.site.contact', ['field' => $this->field, 'err' => ['送信に失敗しました。数時間後もう一回送信してみて下さい。']]);
|
||||
}
|
||||
|
||||
// メールを送る
|
||||
try {
|
||||
Mail::to(config('mail.from.address'))->send(new ContactNotifyMail($this->field, $filename));
|
||||
} catch (\Throwable $e) {
|
||||
Storage::disk('public')->delete($filename);
|
||||
Log::critical($e);
|
||||
return view('pages.site.contact', ['field' => $this->field, 'err' => ['送信に失敗しました。数時間後もう一回送信してみて下さい。']]);
|
||||
}
|
||||
|
||||
Storage::disk('public')->delete($filename);
|
||||
$this->field['kenmei'] = '';
|
||||
$this->field['adr'] = '';
|
||||
$this->field['cat'] = '';
|
||||
$this->field['bunsyo'] = '';
|
||||
$this->field['gpg'] = '';
|
||||
$this->field['ruleapply'] = false;
|
||||
|
||||
return redirect('/contact/seiko');
|
||||
}
|
||||
|
||||
function run ($bin, $command = '', $force = true) {
|
||||
$stream = null;
|
||||
$bin .= $force ? ' 2>&1' : '';
|
||||
|
||||
$descriptorSpec = array(
|
||||
0 => array('pipe', 'r'),
|
||||
1 => array('pipe', 'w')
|
||||
);
|
||||
|
||||
$process = proc_open($bin, $descriptorSpec, $pipes);
|
||||
|
||||
if (is_resource($process)) {
|
||||
fwrite($pipes[0], $command);
|
||||
fclose($pipes[0]);
|
||||
|
||||
$stream = stream_get_contents($pipes[1]);
|
||||
fclose($pipes[1]);
|
||||
|
||||
proc_close($process);
|
||||
}
|
||||
|
||||
return $stream;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ContactNotifyMail extends Mailable {
|
||||
use Queueable, SerializesModels;
|
||||
private $form;
|
||||
private $file;
|
||||
|
||||
public function __construct ($form, $file) {
|
||||
$this->form = $form;
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
public function build () {
|
||||
return $this->from($this->form['adr'])->subject($this->form['kenmei'])->markdown('emails.notify.contact', ['form' => $this->form])->attachFromStorage('public/'.$this->file);
|
||||
}
|
||||
}
|
|
@ -55,6 +55,13 @@ return [
|
|||
'visibility' => 'public',
|
||||
],
|
||||
|
||||
'private' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/private'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'private',
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
|
|
|
@ -41,6 +41,7 @@ return [
|
|||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'sendmail' => '/usr/sbin/sendmail -bs',
|
||||
'timeout' => null,
|
||||
'auth_mode' => null,
|
||||
],
|
||||
|
@ -87,6 +88,10 @@ return [
|
|||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
'owner' => [
|
||||
'address' => env('MAIL_OWNER_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_OWNER_NAME', 'Example'),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
@component('mail::message')
|
||||
# {{ $form['kenmei'] }}
|
||||
|
||||
{{ $form['adr'] }}<br />
|
||||
{{ $form['cat'] }}<br /><br />
|
||||
|
||||
□□□□□□□□□□□□□□□□□□□□<br /><br />
|
||||
|
||||
{{ nl2br($form['bunsyo']) }}
|
||||
@endcomponent
|
|
@ -0,0 +1,15 @@
|
|||
@extends('theme.'.env('THEME').'.site')
|
||||
|
||||
@section('content')
|
||||
<div class="within">
|
||||
<div class="bar">連絡フォーム</div>
|
||||
<div class="back">
|
||||
<div class="alert alert-success" role="alert">
|
||||
@foreach ($suc as $s)
|
||||
{{ $s }}<br />
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
|
@ -0,0 +1,84 @@
|
|||
@extends('theme.'.env('THEME').'.site')
|
||||
|
||||
@section('content')
|
||||
<div class="within">
|
||||
<div class="bar">連絡フォーム</div>
|
||||
<div class="back">
|
||||
@if (!empty($err))
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<ul>
|
||||
@foreach ($err as $e)
|
||||
<li>{{ $e }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
私のGPGはこちらです→ <a href="https://some.very.questionable.website/suwako-gpg.key">suwako-gpg.key</a>
|
||||
<hr />
|
||||
<form method="POST" action="/contact" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>メールアドレス<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col">
|
||||
<input name="adr" type="text" class="form-control" value="{{ $field['adr'] }}" />
|
||||
<span style="font-size: 10px; color: #7f8c8d;">例)notwork@076.ne.jp</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>件名<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col">
|
||||
<input name="kenmei" type="text" class="form-control" value="{{ $field['kenmei'] }}" />
|
||||
<span style="font-size: 10px; color: #7f8c8d;">例)アカウントの作成について</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>カテゴリ<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col">
|
||||
<select name="cat" class="form-control">
|
||||
@foreach ($field['cats'] as $k => $v)
|
||||
<option value="{{ $k }}" @if ($field['cat'] == $k) selected @endif >{{ $v }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span style="font-size: 10px; color: #ed1515;">注意)違うカテゴリを選択すると、メールアドレスをブロックされます!!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>GPG公開キー<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col"><input type="file" name="gpg" /></div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>文章<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col"><textarea name="bunsyo" rows="16" class="form-control">{{ $field['bunsyo'] }}</textarea></div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col-sm-3"><b>連絡ルール<span style="color: #ed1515;">*</span></b></div>
|
||||
<div class="col">
|
||||
<p style="font-size: 80%;">
|
||||
メールを送る前、ちゃんと下記のルールをお読み下さい。<br />
|
||||
ルールを守らないと、送信者様のメールアドレスをブラックリストに追加しますので、ご注意下さい。<br /><br />
|
||||
|
||||
① 件名及び文章にURLを追加できません、「http」や「https」等を消しても駄目です。<br />
|
||||
それの場合、送信者様のメールアドレスをブラックリストに追加します。<br />
|
||||
② 正しいカテゴリを選択して下さい。<br />
|
||||
文章と件名とカテゴリが異なったら、送信者様のメールアドレスをブラックリストに追加します。<br />
|
||||
③ 送るには、GPGパブリックキーは必須です。新規創造するには:「gpg --generate」<br />
|
||||
④ 返事する時も、GPGで暗号されないと、<br />
|
||||
私は返事しません。私のパブリックキーはページの上で御座います。<br />
|
||||
⑤ このフォームで、私のGPGパブリックキーを送ったら、返事しません。<br />
|
||||
⑥ 私は返事しなければ、複数同じメールを送ると、送信者様のメールアドレスをブラックリストに追加します。<br />
|
||||
⑦ 日本語でメールを送信して下さい。他の言語の場合、翻訳機で読めないと、返事しません。
|
||||
</p>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" name="ruleapply" class="form-check-input" id="ruleapply" @if ($field['ruleapply']) checked @endif />
|
||||
<label class="form-check-label" for="ruleapply">すべてのルールを読みました。そうして、全部で同意します。</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row body">
|
||||
<div class="col"><input type="submit" name="submit" class="btn btn-success btn-block" value="送信" /></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
|
@ -32,5 +32,7 @@ Route::group(['prefix' => 'video'], function () {
|
|||
|
||||
Route::get('/memberlist', 'User\MemberList@index');
|
||||
Route::get('/commentlist', 'Home\CommentList@index');
|
||||
Route::get('/contact/seiko', 'Home\Contact@seiko');
|
||||
Route::any('/contact', 'Home\Contact@index');
|
||||
|
||||
Route::get('/{slug}', 'Home\Index@page');
|
||||
|
|
新しいイシューから参照