MacでPostfixを使ってGmail経由でメールを送信する
メールを送信するサービス等を開発していると、メール送信テストをする必要が出てきます。
開発環境でPostfixを使ってGmail経由でメール送信する方法を紹介します。
補足
Postfixのバージョン確認
$ postconf | grep mail_version mail_version = 3.2.2 milter_macro_v = $mail_name $mail_version
手順
1.main.cfでメールの設定を行う
$ sudo vi /etc/postfix/main.cf relayhost = [smtp.gmail.com]:587 mail_spool_directory = /var/spool/mail smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_sasl_mechanism_filter = plain smtp_tls_security_level = may
Postfix2.3以降は「smtp_use_tls = yes」ではなく「smtp_tls_security_level = may」を使います。
http://www.postfix-jp.info/trans-2.3/jhtml/postconf.5.html#smtp_use_tls
smtp_use_tls (デフォルト: no)
この機能はPostfix 2.2以降で使えます。Postfix 2.3以降では smtp_tls_security_level を代わりに使ってください。
2.Googleでアプリパスワードを取得する
以下のサイトを参考にアプリパスワードを取得します。
デバイスは「mac」を選択します。
www.howtonote.jp
3.送信時の認証情報を設定する
# 認証情報の作成 $ sudo vi /etc/postfix/sasl_passwd [smtp.gmail.com]:587 hoge@gmail.com:取得したパスワード # 権限変更 $ sudo chmod 600 /etc/postfix/sasl_passwd # ハッシュ化 $ sudo postmap /etc/postfix/sasl_passwd
4.スプールを設定する
# ディレクトリ作成 $ sudo mkdir /var/spool/mail # 所有者・グループの変更 $ sudo chown ログインユーザー名:staff /var/spool/mail # 権限の変更 $ sudo chmod 700 /var/spool/mail
5.Postfixをリロードする
# すでに起動している場合 $ sudo postfix reload # 停止 $ sudo postfix start # 起動 $ sudo postfix stop
5.メール送信テストを行う
送信前に後で説明するメール送信ログの出力を行います。
$ mail hoge@gmail.com(送信先アドレス) Subject: test # タイトル test # 本文 . # メールを送信する
6.メールが届いているか確認する
メール送信ログ
Macではmaillogが生成されないようなので、メール送信前に以下のコマンドを実行しておきます。
$ log stream --predicate '(process == "smtpd") || (process == "smtp")' --info
次のようなメッセージが表示された場合、メール送信に失敗しています。
(host smtp.gmail.com[74.125.203.108] said: 530-5.7.0 Authentication Required. Learn more at 530 5.7.0 https://support.google.com/mail/?p=WantAuthError o8sm917374pjf.37 - gsmtp (in reply to MAIL FROM command))
送信が成功した場合、次のようなメッセージが表示されればOKです。
to=<hoge@gmail.com>, relay=smtp.gmail.com[2404:6800:4008:c01::6d]:587, delay=2.6, delays=0.02/0.04/1.5/1, dsn=2.0.0, status=sent (250 2.0.0 OK 1595305690 z25sm18507895pfg.140 - gsmtp)
MecurialをGitに変換する
愛用しているバージョン管理サービスのbitbucketでMercurialの提供を終了し、Gitに完全移行するということで、既存のMercurialリポジトリをGitに移行してみました。
記事を公開するまでの期間が長かったため、抜けや間違い等があるかもしれないので、参考程度にしてみてください。
動作環境
Mac
Homebrew
環境構築
MecurialをGitに変換するための環境を構築します。
Pythonの確認
$ python --version Python 2.7.10 # インストールされてなければ $ brew install python2
pipの確認(Pythonのパッケージ管理)
# インストール確認 $ pip -bash: pip: command not found # curlでpipを取得 $ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1764k 100 1764k 0 0 3484k 0 --:--:-- --:--:-- --:--:-- 3488k # pipをインストール $ python get-pip.py --user WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip. Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue. To avoid this problem you can invoke Python with '-m pip' instead of running pip directly. DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Collecting pip Using cached pip-20.0.2-py2.py3-none-any.whl (1.4 MB) Collecting wheel Using cached wheel-0.33.6-py2.py3-none-any.whl (21 kB) Installing collected packages: pip, wheel WARNING: The scripts pip, pip2 and pip2.7 are installed in '/Users/xxxxx/Library/Python/2.7/bin' which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. WARNING: The script wheel is installed in '/Users/xxxxx/Library/Python/2.7/bin' which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location. Successfully installed pip-20.0.2 wheel-0.33.6 # 環境変数を設定 $ vi ~/.bash_profile export PATH=$PATH:$HOME/Library/Python/2.7/bin # 環境変数の有効化 $ source ~/.bash_profile
PythonにMecurialをインストール
$ pip install mercurial DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Defaulting to user installation because normal site-packages is not writeable Collecting mercurial Downloading mercurial-5.2.2.tar.gz (7.3 MB) |████████████████████████████████| 7.3 MB 2.3 MB/s Building wheels for collected packages: mercurial Building wheel for mercurial (setup.py) ... done Created wheel for mercurial: filename=mercurial-5.2.2-cp27-cp27m-macosx_10_14_intel.whl size=2728813 sha256=f0b70639c66146acc92e93b5d1325c68d5ab60eee4f62208d43ba4ad1f47821f Stored in directory: /Users/xxxxx/Library/Caches/pip/wheels/64/d4/95/33110d3cbdbafbd02d90913d03b12064730908962c08990d68 Successfully built mercurial Installing collected packages: mercurial Successfully installed mercurial-5.2.2
MecurialをGitに変換する
変換ツールをダウンロードする
$ git clone https://github.com/frej/fast-export.git
変換
# Mecurialリポジトリに移動 $ cd HgRepo # コミットログの登録ユーザー名を一覧に出力 $ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors # ユーザー名を変換でできる形式に変更 $ vi ../authors # Mecurialでのユーザー一覧 User1 Yamada Taro # 上記を以下の形式に書き換えて保存 "User1"="User1 <user1@gmail.com>" "Yamada Taro"="Yamada Taro <yamada_taro@yahoo.co.jp>" # Mecurialリポジトリ内でGitリポジトリを作成 $ git init # 変換時にエラーが出るので設定を変更しておく $ git config core.ignoreCase false # 変換を実行する $ ../fast-export/hg-fast-export.sh -r . -A ../authors
変換したソースをリモートにプッシュする
# リモート設定 $ git remote add origin https://xxxxx@bitbucket.org/xxxxx/GitRepo.git # プッシュ $ git push origin master # タグを一括でプッシュ $ git push origin master --tags
docker上のPHPでEXIFを使えるようにする
PHPで画像からEXIF情報を取得するには、exif_read_data
関数を使います。
しかし、この関数だけでは動作しないのでEXIFモジュールを追加する必要があります。
docker上でEXIFモジュールを追加する方法をまとめました。
手順
1.Dockerfileに以下を追記します。
RUN && apt-get install -y \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install -j$(nproc) gd exif \
2.Dockerfileを実行しイメージを作成します。
3.PHPでexif_read_data
を実行しエラーが出ないか確認します。
MacBook Pro 2019 でログイン時に画面が乱れる現象
2019年末に6年使ったMacBook Proを2019年モデルに買い替えました。
バタフライキーボードに違和感を覚えながらも、使い続けるとタイピングが心地よくなってきて慣れてきました。
そんな中、使い出してから数回目の起動時に、画面が乱れる現象が発生するようになりました。
画面が乱れる現象とは?
本体起動時にまずパスワード入力画面が表示されます。
そこでパスワードを入力しエンターキーを押すと、データ読み込みの進捗バーが表示されます。
そのバーが半分を少し超えた所で一瞬画面が乱れます。
乱れた後は、何事もなかったかのようにデスクトップが表示されます。
画面が乱れたときの画像は次のような感じです。
ログイン時だけなのであまり気にしてなかったのですが、普通に使っている時も極稀に違うタイプの画面のチラつきが発生します。
対処方法は?
Macでは定番のメンテナンスツール「OnyX」でメンテナンスを行うと画面のチラつきは発生しなくなります。
しかし、数回起動を行うとまた同じような現象が発生します。
特に外部モニターに繋げた後の起動は必ず発生しているような感じです。
2020/05/16 追記
ディスクの暗号化(FileVault)をオフにすると発生しなくなりました。
まとめ
対処方法を書きましたが、一時的な対処であり根本的な解決には至っていません。
ネットで調べるとMacのハードウェアリセットを試したけど効果がなかったとあったので、リセットはまだ試してません。
何かご存じの方いらっしゃいましたら、コメント頂けたら幸いです。
Gradle4.xから6.xで変更する依存関係の定義
Graldeを4.10.2から6.0.1にバージョンアップしたときに警告やエラーが出たので、そのときに変更した依存関係周りを簡単にまとめました。
個人的にGradleはあまり詳しくないので、今回影響があった部分のみの記載です。
さらに詳細を知りたい方は、参考サイトをご覧ください。
バージョンアップ時のエラー
Gradle6にしてビルド等を走らせると、lombokを使用している場合、認識されずコンパイルが通りません。
いつの間にかGradleの設定方法が変わっていたので、その辺を変更します。
依存関係
ライブラリの依存定義に使う設定名が以下のように変わっています。
compile -> implementation compile files -> implementation files runtime -> runtimeOnly providedCompile -> compileOnly
注釈処理
「annotationProcessor
」というものを使う必要があります。
以下、Domaとlombokの場合です。
// Doma annotationProcessor 'org.seasar.doma:doma:2.19.3' implementation 'org.seasar.doma:doma:2.19.3' // lombok annotationProcessor 'org.projectlombok:lombok:1.18.8' compileOnly 'org.projectlombok:lombok:1.18.8'
Domaの場合、追加で以下も必要です。書き方が変わっています。
task copyDomaResources(type: Sync) { from sourceSets.main.resources.srcDirs into compileJava.destinationDir include 'doma.compile.config' include 'META-INF/**/*.sql' include 'META-INF/**/*.script' } compileJava { dependsOn copyDomaResources }
警告の確認
古い定義でもそのまま使えますが、バージョンアップ毎に非推奨の定義があり、将来的に削除されます。
スムーズにバージョンアップするためにも、非推奨定義は別の定義に変更しておいた方が良いです。
非推奨や警告定義の確認は、Gradleの各コマンドで「--warning-mode all
」を付与すると出力されます。
gradle build --warning-mode all
MW WP Formで登録後に自動で投稿する方法
WordPressのフォーム登録プラグイン「MW WP Form」を使って、登録後に自動で投稿する方法を紹介します。
この記事では、登録フォームの設定方法は割愛し、登録後の自動登録の部分のみ説明します。
環境
WordPress 5.2.4
MW WP Form 4.2.0
任意のテーマ
変更箇所
以下に記載のコードを使用中のテーマにある「function.php」に追加します。
フォームで使用するカスタムフィールドを定義する
管理画面の投稿登録画面に登録フォームで使用するカスタムフィールドの入力欄を追加します。
これを設定することで、投稿時に毎回プルダウンからカスタムフィールドを選択する手間が省かれます。
/** * 投稿画面で表示するカスタムフィールドのHTMLを定義します。 * 第2引数で独自の引数を設定することで、textareaまたはtextを生成するようにしています。 */ function write_html($post, $args) { $field_nm = $args['args'][0]; $type = $args['args'][1]; if ($type == 'textarea') { echo '<textarea name="' . $field_nm . '" style="width: 100%; height: 200px;">' . get_post_meta($post->ID, $field_nm, true) . '</textarea>'; } if ($type == 'text') { echo '<input type="text" name="' . $field_nm . '" style="width: 100%;" value="' . get_post_meta($post->ID, $field_nm, true) . '"/>'; } wp_nonce_field( 'send_field1' , 'nonce_for_field_1' ); } /** * 投稿画面にカスタムフィールドを表示します。 * 最後の引数に配列で独自の引数を設定することができます。 */ function add_custom_meta_box() { // 第1引数:項目ごとのdivタグにつくid名(被らないように任意の値) // 第2引数:登録フォームの各入力項目のname // 第3引数:HTMLを生成するコールバック名 // 第4引数:適用するページの種別(postで) // 第5引数:メタボックスの種別(初期値:advanced) // 第6引数:メタボックスの優先度(初期値:default) // 第7引数:第3引数のコールバックで使う任意の引数(必要であればarrayで定義) add_meta_box('custom_field_1','氏名','write_html','post','advanced','default',array('氏名','text')); add_meta_box('custom_field_2','メールアドレス','write_html','post','advanced','default',array('メールアドレス','text')); } add_action('admin_menu', 'add_custom_meta_box');
フォーム登録後に投稿する
MW WP Formで作成した登録フォームからデータが登録されたら、投稿するようにします。
処理内容は、投稿を新規登録し、カスタムフィールドを別テーブルに登録します。
function update_meta_posts($Mail_admin, $Data) { // 登録フォームから入力データを取得 $form_data = $Data->getInstance(); // 投稿新規データを作成(タイトルと公開状態の2つの最低限) $post = array( 'post_title' => $form_data->get('募集タイトル'), 'post_status' => 'publish' ); // 上記データで投稿を新規登録 $post_id = wp_insert_post($post, true); // 登録フォームのカスタムフィールドを別テーブルに登録 update_post_meta($post_id, '氏名', $form_data->get('氏名')); update_post_meta($post_id, 'メールアドレス', $form_data->get('メールアドレス')); } // アクションフックを追加 // 第1引数:末尾の数字は、登録フォーム作成時のショートコードを設定 // 第2引数:フック実行時の処理 // 第3・4引数:説明がないので用途は不明(固定値??) add_action('mwform_before_send_admin_mail_mw-wp-form-8', 'update_meta_posts', 10, 2);
参考サイト
mwform_before_send_admin_mail_mw-wp-form-xxx | MW WP Form
- 作者: 野島祐慈,菱川拓郎,杉田知至,細谷崇,枢木くっくる
- 出版社/メーカー: 技術評論社
- 発売日: 2017/01/26
- メディア: Kindle版
- この商品を含むブログを見る
LINQでグルーピングした最大の要素を取得する
C#でグルーピングして最大の要素を取得したかったので、試行錯誤して調べた結果、Max
ではなくOrderByDescending
を使うことで実現できました。
まだまだLINQは、使い慣れてないのでちょっと特殊なことをしようとするとハマって時間が取られてしまいました…。そんなんでお困りの方、ご参考に。
少し解説すると、以下のようになります。
GroupBy
・第1引数:元の値を何でグループ化するかを指定する
・第2引数:元の値をグループ化したものに対して、キーと値の2つの引数が使え、値に対しての処理を指定する
OrderByDescending
元の値を第1引数で指定したもので昇順に並べ、First
を指定することで先頭を取得する
サンプルコード
// 値を持つクラス public class Hoge { public int Key { get; set; } public string Dt { get; set; } } // グルーピングして最大を取得する処理 public void Main(string[] args) { // 値の設定 List<Hoge> list = new List<Hoge> { new Hoge() { Key = 1, Dt = "20190101" }, new Hoge() { Key = 1, Dt = "20190102" }, new Hoge() { Key = 2, Dt = "20190101" }, new Hoge() { Key = 3, Dt = "20190310" }, new Hoge() { Key = 3, Dt = "20190305" }, new Hoge() { Key = 3, Dt = "20190301" }, new Hoge() { Key = 4, Dt = "20190101" }, new Hoge() { Key = 4, Dt = "20190102" }, new Hoge() { Key = 5, Dt = "20190103" }, }; // Key毎にDtが最大の要素を取得 List<Hoge> retList = list .GroupBy( h => h.Key, (k, v) => v.OrderByDescending(o => o.Dt).First()) .ToList(); // 結果 retList.ForEach(f => Console.WriteLine("{0} {1}", f.Key, f.Dt)); }
結果
1 20190102 2 20190101 3 20190310 4 20190102 5 20190103
Key毎にDtが最大の要素がListに格納されています。