2026-02-27

Windows11でMicrosoft Flight Simulator 2002を動かすためにdgVoodoo2を利用した

昨年秋のWindows 10のサポート終了により、Windows 11にしました。Windows 10を動かしていたマシンは、Windows 8の頃に購入したので、Windows 11のハードウェア要件を満たしておらず、新しいマシンに買い替えました。Windows 10でMicrosoft Flight Simulator 2002を動かしていましたが、特に問題はありませんでした。ところがWindows 11では、起動するし、メニュー操作などもできますが、フライト始めると数秒でプログラムが落ちてしまいます。イベントログを確認すると、メモリのアクセス違反が起きているようです。

 

MSFS2002の動作設定で「ハードウェア アクセラレーションを使用」という設定を解除できます。こうすれば、プログラムが落ちることはないのですが、画面描画がうまくいかず、フラストレーションがたまります。

 

なんとかならないだろうかと、Geminiに相談してみたところ、無事に解決しました。Geminiが提示してきた解決策は、以下の3つです。

  1. 互換モード(Windows XP SP3 / 管理者として実行)
  2. DEP(データ実行防止)の設定
  3. dgVoodoo2 の導入 

 

最終的に効果があったのは「dgVoodoo2」です。こういうものがあるとは、Geminiに教えられるまで知りませんでした。Web検索すると「dgVoodoo2でラグナロクオンラインを快適に遊ぶ」という記事が見つかりました。また解決策2は不要とのことで、最終的に解決策1と3をおこなうことで、解決に至りました。

 

MSFS2002は、名前の通り2002年に発売されているので、もう20年以上も前の製品です。Windows XPの時代です。そんな大昔のソフトウェアが、多分動かないだろうと半ば諦めていたので、藁にも縋る思いでGeminiに相談して、解決したので嬉しいです。そしてGeminiとの向き合い方も分かってきた気がします。 

2026-02-26

NFD形式ファイルをFDI形式に変換するスクリプトを作成

Windows11上のT98-NEXTでWizardryをプレイするとNFD形式でフロッピーディスクイメージが作られます。これをNetBSD/i386上のxnp2で利用するにはFDI形式に変換しなくてはなりません。NFD形式とFDI形式の構造について調べたので、NFD→FDIの変換をおこなうスクリプトを作りました。この目的はWizardryでプレイしたファイルを変換したいだけなので、大雑把な作りになっています。 

以前なら、GoogleなどでWebを検索して、参考となるサイトを探していました。今でも同様なのですが、最近はGeminiと対話しながら、作成するようになりました。世間一般では、生成されたスクリプトを何も考えずに使うだけなのか、それとも生成されたものを参考にしながら自前で作るのか、どうしているのかはわかりません。私の場合には、Geminiが生成したスクリプトを参考にして、自分で作り上げるようにしています。

その結果、以下のようなスクリプトが出来上がりました。これを使用して、T98-NEXTが出力したNFD形式ファイルを変換してみました。それをxnp2で読み込んでみましたが、問題ないようです。これでT98-NEXT(NFD)→xnp2(FDI)ができるようになったので、途中まで冒険した続きができます。xnp2が出力するファイルはFDI形式になりますが、T98-NEXTはFDI形式も読めるので、FDI→NFD変換スクリプトは作らなくても良いでしょう。

#!/usr/bin/python3
import os
import pathlib
import sys
import ctypes

# 基本的な型のエイリアス
BYTE  = ctypes.c_uint8
WORD  = ctypes.c_uint16
DWORD = ctypes.c_uint32

# セクタ情報
class NFD_SECT_ID(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("C",        BYTE),
        ("H",        BYTE),
        ("R",        BYTE),
        ("N",        BYTE),
        ("flMFM",    BYTE),
        ("flDDAM",   BYTE),
        ("byStatus", BYTE),
        ("byST0",    BYTE),
        ("byST1",    BYTE),
        ("byST2",    BYTE),
        ("byPDA",    BYTE),
        ("Reserve1", ctypes.c_char * 5),
    ]

# NFDヘッダ
class NFD_FILE_HEAD(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("szFileID",    ctypes.c_char * 15),
        ("Reserve1",    ctypes.c_char * 1),
        ("szComment",   ctypes.c_char * 0x100),
        ("dwHeadSize",  DWORD),
        ("flProtect",   BYTE),
        ("byHead",      BYTE),
        ("Reserve2",    ctypes.c_char * 10),
        ("si",          NFD_SECT_ID * (163 * 26)),
        ("Reserve3",    ctypes.c_char * 0x10),
    ]

# FDIヘッダ
class FDI_FILE_HEAD(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("Reserve1",   DWORD),
        ("dwMedia",    DWORD),
        ("dwHeadSize", DWORD),
        ("dwDataSize", DWORD),
        ("dwSectSize", DWORD),
        ("dwSecter",   DWORD),
        ("dwHead",     DWORD),
        ("dwCylinder", DWORD),
        ("Reserve2",   ctypes.c_char * (4096 - 4 * 8)),
    ]

if __name__ == "__main__":
    try:
        nfd = open(sys.argv[1], "br")
    except:
        print("usage: NFD2FDI <filename>")
        exit(1)

    try:
        nfdpath = pathlib.Path(sys.argv[1])
        fdi = open(nfdpath.with_suffix(".FDI"), "wb")
    except:
        print("cannot open FDI file")
        exit(1)

    NFDheader = NFD_FILE_HEAD()
    nfd.readinto(NFDheader)

    FDIheader = FDI_FILE_HEAD()
    FDIheader.dwMedia = 0x90
    FDIheader.dwHeadSize = 4096
    FDIheader.dwSectSize = 256
    FDIheader.dwSecter = 26
    FDIheader.dwHead = 2
    FDIheader.dwCylinder = 77
    FDIheader.dwDataSize = (FDIheader.dwSectSize
                            * FDIheader.dwSecter
                            * FDIheader.dwHead
                            * FDIheader.dwCylinder)


    try:
        nfd.seek(NFDheader.dwHeadSize)
        rawdata = nfd.read(FDIheader.dwDataSize)
        fdi.write(FDIheader)
        fdi.write(rawdata)
    except:
        print("read/write error")
        exit(1)

    exit(0)
#[EOF]

FDI形式ファイルの構造を出力するスクリプトを作成

Windows11上のT98-NEXTでWizardryをプレイするとNFD形式でフロッピーディスクイメージが作られます。これをNetBSD/i386上のxnp2で利用するにはFDI形式に変換しなくてはなりません。変換スクリプトを作成する前に、FDI形式について学ぶため、ファイル内の構造を出力するスクリプトを作ってみました。
 
以前なら、GoogleなどでWebを検索して、参考となるサイトを探していました。今でも同様なのですが、最近はGeminiと対話しながら、作成するようになりました。世間一般では、生成されたスクリプトを何も考えずに使うだけなのか、それとも生成されたものを参考にしながら自前で作るのか、どうしているのかはわかりません。私の場合には、Geminiが生成したスクリプトを参考にして、自分で作り上げるようにしています。 

その結果、以下のようなスクリプトが出来上がりました。これを使ってWizardryで使用しているファイルを参照してみると、いろいろと勉強になります。 

 #!/usr/bin/python3
import sys
import ctypes

# 基本的な型のエイリアス
DWORD = ctypes.c_uint32

# ヘッダ
class FDI_FILE_HEAD(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("Reserve1",   DWORD),
        ("dwMedia",    DWORD),
        ("dwHeadSize", DWORD),
        ("dwDataSize", DWORD),
        ("dwSectSize", DWORD),
        ("dwSecter",   DWORD),
        ("dwHead",     DWORD),
        ("dwCylinder", DWORD),
        ("Reserve2",   ctypes.c_char * (4096 - 4 * 8)),
    ]

if __name__ == "__main__":
    try:
        f = open(sys.argv[1], "br")
    except:
        print("usage: FDIdump <filename>")
        exit(1)

    header = FDI_FILE_HEAD()
    f.readinto(header)

    print(f"dwMedia:0x{header.dwMedia:08x} ({header.dwMedia})")
    print(f"dwHeadSize:0x{header.dwHeadSize:08x} ({header.dwHeadSize})")
    print(f"dwDataSize:0x{header.dwDataSize:08x} ({header.dwDataSize})")
    print(f"dwSectSize:0x{header.dwSectSize:08x} ({header.dwDataSize})")
    print(f"dwSecter:0x{header.dwSecter:08x} ({header.dwSecter})")
    print(f"dwHead:0x{header.dwHead:08x} ({header.dwHead})")
    print(f"dwCylinder:0x{header.dwCylinder:08x} ({header.dwCylinder})")

    print("header size:", ctypes.sizeof(FDI_FILE_HEAD))

#[EOF]

NFD形式ファイルの構造を出力するスクリプトを作成

Windows11上のT98-NEXTでWizardryをプレイするとNFD形式でフロッピーディスクイメージが作られます。これをNetBSD/i386上のxnp2で利用するにはFDI形式に変換しなくてはなりません。変換スクリプトを作成する前に、NFD形式について学ぶため、ファイル内の構造を出力するスクリプトを作ってみました。

 

以前なら、GoogleなどでWebを検索して、参考となるサイトを探していました。今でも同様なのですが、最近はGeminiと対話しながら、作成するようになりました。世間一般では、生成されたスクリプトを何も考えずに使うだけなのか、それとも生成されたものを参考にしながら自前で作るのか、どうしているのかはわかりません。私の場合には、Geminiが生成したスクリプトを参考にして、自分で作り上げるようにしています。

 

その結果、以下のようなスクリプトが出来上がりました。これを使ってWizardryで使用しているファイルを参照してみると、いろいろと勉強になります。 

 

#!/usr/bin/python3
import sys
import ctypes

# 基本的な型のエイリアス
BYTE  = ctypes.c_uint8
WORD  = ctypes.c_uint16
DWORD = ctypes.c_uint32

# セクタ情報
class NFD_SECT_ID(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("C",        BYTE),
        ("H",        BYTE),
        ("R",        BYTE),
        ("N",        BYTE),
        ("flMFM",    BYTE),
        ("flDDAM",   BYTE),
        ("byStatus", BYTE),
        ("byST0",    BYTE),
        ("byST1",    BYTE),
        ("byST2",    BYTE),
        ("byPDA",    BYTE),
        ("Reserve1", ctypes.c_char * 5),
    ]

# ヘッダ
class NFD_FILE_HEAD(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("szFileID",    ctypes.c_char * 15),
        ("Reserve1",    ctypes.c_char * 1),
        ("szComment",   ctypes.c_char * 0x100),
        ("dwHeadSize",  DWORD),
        ("flProtect",   BYTE),
        ("byHead",      BYTE),
        ("Reserve2",    ctypes.c_char * 10),
        ("si",          NFD_SECT_ID * (163 * 26)),
        ("Reserve3",    ctypes.c_char * 0x10),
    ]

if __name__ == "__main__":
    try:
        f = open(sys.argv[1], "br")
    except:
        print("usage: NFDdump <filename>")
        exit(1)

    header = NFD_FILE_HEAD()
    f.readinto(header)

    print(f"szFileID:{header.szFileID}")
    print(f"szComment:{header.szComment}")
    print(f"dwHeadSize:{header.dwHeadSize} (0x{header.dwHeadSize:X})")
    print(f"flProtect:{header.flProtect}")
    print(f"byHead:{header.byHead}")

    for i in range(len(header.si)):
        print(f"{i:4}:  ", end="")
        print(f"C:{header.si[i].C:02x} ", end="")
        print(f"H:{header.si[i].H:02x} ", end="")
        print(f"R:{header.si[i].R:02x} ", end="")
        print(f"N:{header.si[i].N:02x} ", end="")
        print(f"MFM:{header.si[i].flMFM} ", end="")
        print(f"DDAM:{header.si[i].flDDAM} ", end="")
        print(f"Status:{header.si[i].byStatus:02x} ", end="")
        print(f"ST0:{header.si[i].byST0:02x} ", end="")
        print(f"ST1:{header.si[i].byST1:02x} ", end="")
        print(f"ST2:{header.si[i].byST2:02x} ", end="")
        print(f"PDA:{header.si[i].byPDA:02x} ", end="")
        print(f"addr:{(header.dwHeadSize + i * 256):08x}")
#[EOF]
 

2026-02-25

NetBSD/i386 9.4でThunderbirdを動かそうとしたが断念したものの、Geminiとの対話は役に立った

NetBSD/i386 9.4のMATEデスクトップ環境が復活したので、Thunderbirdを入れてみようと思い立ちました。随分前にはpkgsrcでThunderbirdをインストールした記憶がありますが、何時の頃からかpkgsrcからは消えてしまいました。

 

NetBSDネイティブでなくても、LibreOfficeのようにLinuxエミュレーション環境でなんとかならないか試してみました。Geminiに相談しながら、インストールを試みます。インストール事態は、入手したファイルを展開するだけなので、別に難しくはありません。しかし実行しようとするとエラーが出ます。ここでGeminiに相談すると、いろいろとアドバイスしてくれます。

 

Geminiとの対話を繰り返しながら、あれこれやってみましたが、最終的にThunderbirdを動かすことはできないという結論に至りました。それはそれで構わないのですが、Geminiとの対話は、とても有効だったと感じました。Geminiのアドバイスが常に正確で間違いないという訳ではないのですが、それは現実の「詳しい知人」であっても似たようなものです。「詳しい知人」に比べてれば、Geminiの方が詳しい(知識量が多い)と思います。しかも「詳しい知人」は、機嫌を損ねると、へそを曲げたりしますが、Geminiには、そのような心配はありません。

 

Gemini(というか生成AI)は、うまく使えば、とても便利だと思います。しかし、Geminiが常に正しい情報を伝えてくれるわけでもなく、その伝えてくる情報を吟味して、何をするのか自分自身が理解している必要があると思います。Geminiがあれば、自分は勉強しなくても良いわけではなく、むしろ更に勉強しなければならないでしょう。

 

Geminiにも出来ることと出来ないことがあると思いますが、うまく使いこなせれば、とてもメリットがあると思います。 

T98-NEXTのNFD形式はxnp2では扱えなかった

NetBSD/i386でxnp2が動くようになり、PC-9801用Wizardryが動作したので、Windows 11上のT98-NEXTで保存したファイルを使おうとしたら、認識されませんでした。T98-NEXTではNFD形式ですが、xnp2はFDI形式を期待しているようです。FDイメージファイルの形式は、なんでも良いかと思っていましたが、そうでもないようです。

 

ネットを検索すると、FDイメージファイルの形式を変換するプログラムが見つかりました。NFD形式からFDI形式に変換できましたが、xnp2では認識されません。

 

変換されたフィルを確認すると、認識されるFDI形式とはファイルサイズが違うようです。強引ですが、バイナリエディタを使い、余分なところを切り詰めてみました。そうしたら、xnp2でも認識されるようになりました。

 

これで、Windows11上のT98-NEXTで途中までプレイした結果ファイル(NFD形式)を、FDI形式に変換し、末尾を切り落として、NetBSD/i386にコピーすれば、xnp2で続きをプレイできます。途中の手順がやや面倒ですが、機械的に処理する方法を探ってみようと思います。

2026-02-24

NetBSD/i386 9.4上のxnp2 0.86でPC-9801用Wizardryが動いた

NetBSD/i386 9.4にxnp2 0.86をインストールできたので、PC-9801用のWizardryを動かしてみました。何のトラブルに見舞われることもなく、あっさりと動作しました。

 

Windows11上でT98-NEXTを使っている場合には、FDイメージのファイルには拡張子「.NFD」がつくのですが、xnp2は「.FDI」か「.D88」を期待するようです。しかしこれは拡張子のネーミングの問題に過ぎないと思うので、FDイメージの構造が異なるわけではないでしょうから、おそらく問題にはならないと思います。

 

 xnp2は、FDイメージファイルをアクセスする際に、FDドライブのシーク音を出します。これはT98-NEXTには無かった機能です。物理的なFDドライブが存在するわけではないので、気分の問題ですが、シーク音を耳にすると懐かしさを覚えます。またリセット直後には、おなじみの「ピポッ」という音がなります。これはT98-NEXTもそうでした。これが聞こえるとPC-9801の思い出が蘇ります。

 

これで、Windows11上のT98-NEXTと、NetBSD/i386上のxnp2で、Wizardryが遊べるようになりました。両方の環境を使って遊ぶには、途中経過を記録したFDイメージの取り扱いが問題になってくるでしょう。何か良い方法を考えようと思います。 

NetBSD/i386 9.4でxnp2 0.86が動作した

NetBSD/i386 9.4環境で、パッケージからnxp2をインストールしようとしました。そうしたら共有ライブラリの不整合が発生し、pkgin full-upgradeを実行しました。するとエラーが出て、Geminiに相談しながら調査したら、パッケージ管理ディレクトリが/var/db/pkgと/usr/pkg/pkgdbの2箇所に見つかり、これが原因で深刻な不整合が起きていることが発覚しました。Geminiのアドバイスを受けながら、インストール済みの全パッケージを削除し、入れ直しました。しかし欠けているパッケージがあるので、確認しながら、追加インストールして、ようやくMATEデスクトップ環境が復活しました。

 

あらためて、本来の目的だったxnp2をインストールしました。何も問題がなくインストールできました。

 

動かしてみたのですが、PC-9801の起動時画面が出るはずですが、文字がかすれて読めません。フォントを別途入手する必要があるようです。Neko Project 21/Wのサイトから「font.bmp」を入手して「~/.np2/font.bmp」に置きました。これで起動時画面の文字が読めるようになり、一歩前進です。

 

次は、Wizardryが動くか確認しようと思います。 

2026-02-23

NetBSDのパッケージ管理情報が/usr/pkg/pkgdbと/var/db/pkgで混乱していた

NetBSD/i386にxnp2を入れようとしたら、共有ライブラリのトラブルが発生したので、pkginを使ってfull-upgradeを試みました。そうしたら、MATEが消えてしまい、ログインできなくなりました。あらためてpkginでMATEをインストールしようとしたら、多くのエラーメッセージが出て、インストールできません。

 

以前であれば、問題解決のためにGoogleで検索して似たような事例を探していたのですが、最近はGeminiに相談するようになりました。MATEのパッケージがインストールできないので解決したいというのが、Geminiに相談したことなのですが、Geminiがアドバイスしてくれたコマンドを叩くとエラーが発生します。それをGeminiに伝えると、また別のアドバイスをくれるので、対話を繰り返していると、次第に深みにはまってきました。

 

トラブルの根本原因は、NetBSDのパッケージ管理情報が/usr/pkg/pkgdbと/var/db/pkgの2か所に存在していることが判明しました。このように2か所に存在しているので、双方の情報が重複したりしていて、不整合も発生しているようです。こうなってしまうと、MATEがどうこうという問題よりも、この不整合を如何に解決するかという方が、重大な問題になりました。

 

Geminiのアドバイスを貰いながら対処を試みましたが、深刻な障害が解消しません。多少強引ですが、最後の奥の手として、インストール済みのパッケージをリストしておき、インストール済み全パッケージを削除し、あらためてインストールしなおすことにしました。

 

今は、インストール済のパッケージを削除しているところです。1,000以上ものパッケージがインストールされていたので、削除するだけでも長時間かかります。削除が終わったら、再インストールしますが、それも長時間かかるでしょう。 

NetBSDにバイナリパッケージxnp2を入れたらMATEが動かない

NetBSDのパッケージにはPC98エミュレータxnp2が含まれていることがわかったので、バイナリパッケージを入れてみました。バイナリパッケージを入れるのに「pkgin」を利用しています。OSがNetBSD/i386 9.0なので、パッケージ2025Q4のNetBSD/i386の9.0用を参照しました。

 

xnp2に依存関係のあるパッケージが有るのか無いのか不明ですが、最近1年以上もパッケージを更新していなかったので、追加更新に60個弱のパッケージが必要になりました。各々のパッケージが本当に必要なのか厳密に確かめることができるかもしれませんが、それをするなら「pkgin」を使う意味がないと思い、それらのパッケージを全てインストールしました。

 

インストール自体には問題がありませんでしたが、ログインできなくなりました。正確には、XDMでログインしたあとで、MATEを動かしているのですが、共有ライブラリが見つからないとのことで、XDMログイン画面に戻ってしまいます。rootは、MATEではなく,TWMのままなので、問題ありませんでした。「~/.xsession-errors」を確認すると、共有ライブラリが見つからないとあります。確かにその通りでしたが、シンボリックリンクを張れば解決できそうなので、対処しました。そして再度ログインしてもXDMに戻ってしまいます。別の共有ライブラリが見つからないようです。これを繰り返したら、最終的に共有ライブラリに定義されていないものがあるというエラーになりました。

 

もうお手上げなので、Geminiに相談したら、libxkbcommonという共有ライブラリを再インストールすることを勧められました。やってみましたが、解決しませんでした。それをGeminiに訴えると「pkgin full-upgrade」を試してみるように言われました。これなら解決できそうですが、作業時間が長いですし、xnp2とは関係ないところで、別な不具合が出てくるかもしれません。

 

しかし、これ以外に対処方法はないと思うので、もう後戻りはできない状態になっています。何か別の問題がでたら、また解決方法を模索するしかないでしょう。 

2026-02-21

NetBSDでPC98エミュレータ

Windows 10を使っていたころに、T98-NEXTというPC98エミュレータを使ってWizardryを遊んでいました。「PC-9800シリーズエミュレータの現況」という記事によると、PC98エミュレータは他にもあるようです。しかしMicrosoft Windowsなら選択肢は多いかもしれませんが、非Windowsでは選択肢が限られると思います。

 

ちょっと検索したら、次のような記事が見つかりました。これらの記事では、NP2kai(Neko Project II 0.86 kai)を使って、ソースからビルドしているようです。OSにはUbuntuを使っているようなのですが、私はNetBSD/i386を使いたいのです。

 

上述した記事を参考にすれば、NetBSD/i386環境であっても、ソースからビルドできるのではないかと思います。ビルド環境を整えたり、ビルドしてみてエラーが出るかもしれませんし、何かと手間がかかるだろうとは思います。もしかしたら何の苦労もなくビルドできてしまう可能性もありますが、そう簡単ではないだろうと予想しています。

 

自前でビルドする前に、ちょっとパッケージを確認したら、なんと「emulators/xnp2」がありました。これは「Xnp2 is a port for UNIX with X11 of "Neko Project II" PC-9801 emulator.」だそうです。自前でビルドしなくても、既にパッケージが用意されていました。

 

このパッケージをインストールしてみようと思います。このPC98エミュレータでWizardryを動かしてみようと考えていますが、問題なく無事に動いてくれるか心配です。もしトラブルようであれば、デバッグすることになるかもしれませんので、自前でビルドできる環境を整えておく必要が出てくるかもしれません。 

2026-02-18

モバイルSuicaを使ってみる

スマホにモバイルSuicaの設定を済ませたので、実際に利用してみました。何かトラブルが発生するのではないかと戦々恐々だったのですが、何事もなく、あっさりと利用できました。あまりにも何も問題がないので、驚いています(問題がなくて、あたりまえだとは思いますが)。

 

強いて言えば、スマホケースにストラップを付け、胸に下げているのですが、そのため改札を通る際に、多少腰をかがむ必要があるくらいでしょうか。


この調子なら、Smart ICOCAのクイックチャージのサービスが終了しても、モバイルSuicaに移行出来そうです。

2026-02-14

/var/spool/clientmqueue

FreeBSD/amd64を使用して自宅のメール環境を構築しています。fetchmailで取り込み、procmailで振分け、GNUSでメールを読んでいます。メールを送る時はmewを使うか、場合によってはMicrosoft Windows上のThunderbirdを使用しています。数日前、procmailを呼び出すのに、.forwardで指定するのを止めて、.fetchmailrcに変更したところでした。

 

procmailの呼び出し方法を変えただけなので、これまでと同様にメールが振り分けられるはずです。実際その通りなのですが、FreeBSD/amd64自身のrootが送信したメールが見当たらないことに気づきました。root宛のメールは、aliasesでローカルユーザに渡しています。

 

まず最初に確認するのはログファイルです。/var/log/maillogを除くと、エラーが記録されています。同じようなエラーが何度も出力されているようです。目視した限りでは、次のエラーでした。

  1. alias database /etc/mail/aliases.db out of date
  2. get_error=error:0A000126:SSL routines::unexpected eof while reading
  3. info=Bare carriage return (CR) not allowed

 

1番目のエラーは、Webを検索すると「FreeBSD: サーバーOS更新 12.3 → 12.4」という情報が見つかりました。newaliasesすれば良さそうです。

 

2番目と3番目は手強そうなので、Geminiに助けを求めました。Geminiは、「その問題なら、こうすれば解決しますよ」とか気軽に応答するのですが、なかなか解決に至りません。しかも提示された解決策を試みるとエラーが出るので、それを報告すると、「すいません、間違っていました。本当は、この方法です」と別な方法を示してきます。生成AIの回答らしいと言えば、そのとおりです。その分野のエキスパートに尋ねても、やっぱりこうなるかもしれません。生成AIなら、現実の人間と違って、何度訊き返しても嫌がったり怒り出したりする心配がないのは、メリットのような気がします。

 

Geminiとの対話を2時間ほど費やしたあげく、なんとか解決に至りました。いろいろ試したし、試行した内容を取り消したりもしたので、混乱しましたが、次のような対策を講じました。

  1. /etc/mail/ホスト名.submit.mcに「FEATURE(`msp', `[127.0.0.1]', `MSA', `E')」を追加した。
  2. /etc/mail/ホスト名.mcに「DAEMON_OPTIONS(`Name=IPv4, Family=inet, Modifiers=b')」と変更した。IPv6の方も同様に変更した。

 

このように変更してsendmailサービスを再起動すると、溜まっていたメールが流れる「はず」だったのですが、溜まったままでした。Geminiも半ばお手上げ状態で、スプールにあるメールを「tr -d '\r'」しながら、senmailに渡し、強制的に配送しました。これが成功したので、スプールにあるファイルは物理的に削除しました。

 

そもそも、何故このような事態に陥ってしまったのか、その原因は不明です。前回と今回の問題解決において、Gemini(というか生成AI)の威力を実感しました。それと同時に、間違い(勘違い?)を含む回答もしてくるので、Geminiの回答を鵜呑みにするわけにはいかないだろうと思います。そういう意味で、Geminiの指示に淡々と従うわけにはいかないでしょう。生成AIがあれば、何も勉強しなくても万々歳とはならないと思います。 

2026-02-12

BIMI-Indicator

自宅では、FreeBSD/amd64を使用してメール環境を構築しています。fetchmailで取り込み、procmailで振分け、GNUSで読んでいます。つい最近になって、ふと気づくと/var/spool/mqueueに配送できなかったメールが溜まっていることに気づきました。

 

溜まっているファイルを確認したら「SMTP error: 552 5.6.0 Headers too large (32768 max)」というエラーが記録されています。他のファイルも同様でした。このメッセージを手掛かりにWebを検索してみたのですが、解決に至る情報がみつかりませんでした。そこでGeminiに助けを求めてみました。

 

Geminiとの対話では、このメッセージを提示するところから始めました。これだけの情報では、一般論しか返ってこないので、対話を繰り返しながら、問題が解決できるような方向に話を進めました。解決策は幾つかあるようです。これまでは、上述したように、fetchmailで取り込み、.forward経由でprocmailを呼び出して振分けていました。.forwardを利用することでsendmailが介入することになりますが、問題となっているメールには「BIMI-Indicator」という巨大なヘッダがついていて、これが根本的な問題だろうと思います。

 

メッセージが指摘するように「Headers too large」なので、sendmailが「32768 max」という制限をかけているのを緩和するのも一つの方法です。他の方法として、fetchmailから直接procmailを呼び出すこともできて、そうすれば.forwardを使わないので、sendmailが介入することもありません。こちらの方法を採用することとして、.fetchmailrcに設定を追加しました。

 

対策を講じたことで、問題は解決したようです。

 

本来であれば、巨大な「BIMI-Indicator」というヘッダをつけている送信元が対処して欲しいところです。サイトのメールサーバの設定によっては、32kで制限をかけているところがあるでしょうから、そこでも問題が発生しているのではないかと思います。