FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour DEFINE MAIL / TO clause — recipient field empty in Thunderbird with FWH 26.03 (32-bit)
Posts: 184
Joined: Thu Apr 17, 2008 02:38 PM

DEFINE MAIL / TO clause — recipient field empty in Thunderbird with FWH 26.03 (32-bit)

Posted: Sun Jul 19, 2026 10:35 AM

Hello, I'd like to report a possible behavior change between FWH 26.03 (32-bit) and previous versions regarding the DEFINE MAIL command / MAPISendMail(). Environment:

FWH 26.03, 32-bit build Default mail client: Mozilla Thunderbird (set as system MAPI client)

Code used (unchanged for several versions, worked correctly until the previous FWH version): DEFINE MAIL oMail ; SUBJECT cOggetto ; TEXT cTesto ; FILES cFile , cFileNoPath( cFile ) ; TO cEmail ; FROM USER

ACTIVATE MAIL oMail Observed behavior: With FWH 26.03, Thunderbird opens correctly with subject, body and attachment, but the recipient ("To:") field is empty, even though a valid, non-empty cEmail is passed. Analysis: I checked mail.ch and the command translation rule: #xcommand DEFINE MAIL [<oMail>] ... [ TO <cTarget1> [,<cTargetAddress1>] ... ] => ... \{ [ \{<cTarget1>,<cTargetAddress1>\} ] ... \}, ... When only one parameter is passed after TO (just cEmail, without a second "address" parameter), the preprocessor generates a single-element sub-array: { { cEmail } }, where cEmail ends up in the "name/target" slot, while the "address" slot (cTargetAddress1) is completely absent, not just empty. Hypothesis: in previous versions, the C code of MAPISendMail() likely had a fallback (if lpszAddress was empty, use lpszName as the address too), which masked this incomplete syntax. Outlook still resolves the name as an address on its own; Thunderbird's stricter Simple MAPI implementation leaves the "To:" field empty if lpszAddress isn't explicitly set. Verified workaround: Explicitly pass the address twice: TO cEmail, cEmail so that both the "name" and the "address" fields in the MapiRecipDesc struct are populated with the correct email address. Questions for support:

Is this an intentional change in how MAPISendMail() builds the MAPI struct (e.g. removal of a name→address fallback), or an unintended regression? If intentional, it would be worth documenting explicitly, since the TO <cTarget1> [,<cTargetAddress1>] pattern with a single parameter is very common in existing user code (including mine, originally copied from examples posted on this very forum).

Thanks in advance for any feedback. Best regards

Posts: 44508
Joined: Thu Oct 06, 2005 05:47 PM

Re: DEFINE MAIL / TO clause — recipient field empty in Thunderbird with FWH 26.03 (32-bit)

Posted: Sun Jul 19, 2026 03:53 PM

Dear Mauri,

The behavior you observed is consistent with the current source code, but I could not find evidence of a recently‑removed name→address fallback. Here's what the code actually does.

How the recipient array is built

The DEFINE MAIL ... TO <cTarget1> [,<cTargetAddress1>] command expands, via include/mail.ch, into a nested array where each recipient is { <cTarget1>, <cTargetAddress1> }. 0-cite-0

When only one argument follows TO, the sub‑array is { cEmail } — the second (address) slot is genuinely absent, exactly as you described. 0-cite-1

This array is passed as ::aRecipients into MAPISendMail() from TMail:Activate(). 0-cite-2

The C side (MAPISENDMAIL)

In source/winapi/mapi.c, each recipient's lpszName and lpszAddress are read directly from positions 1 and 2 of the sub‑array, with no fallback: 0-cite-3

target[ w ].lpszName     = ( LPSTR ) hb_parvc( -1, 1 );
target[ w ].lpszAddress  = ( LPSTR ) hb_parvc( -1, 2 );

If the address slot is missing, hb_parvc( -1, 2 ) returns NULL, so lpszAddress is left null. There is no if( !lpszAddress ) lpszAddress = lpszName; fallback anywhere in this function. 0-cite-4

On the "regression" hypothesis

I checked the git blame for these exact lines. Both the lpszName/lpszAddress assignments date back to commit e3078b06 (2009‑08‑17) and have not changed since. 0-cite-3

The most recent commit touching mapi.c in the 26.03 timeframe is 6aa0c522 (2026‑06‑13), described as clearing GCC/MSVC compiler warnings "while preserving behavior". Its documented mapi.c‑area changes are cast/indentation fixes (e.g. the GetProcAddress ( void (*)( void ) ) idiom), not logic changes to how recipients are built.

So, based on the source in this repo, the fallback you hypothesize does not exist in the current code and does not appear to have been recently removed from the recipient‑building logic. The behavior — passing only a name and leaving lpszAddress null — has been the same in this source for a long time. What differs is the MAPI client: Outlook resolves the name into an address; Thunderbird's stricter Simple MAPI leaves "To:" empty when lpszAddress is null. This matches your analysis of the observed symptom.

Caveat: I can only inspect the source currently in master. I cannot see the exact binaries you ran for "the previous version" versus 26.03, so I cannot fully rule out a behavior difference introduced elsewhere (for example in the preprocessor expansion or a rebuilt library) without diffing the specific builds. If you want this confirmed against the actual 26.03 vs previous builds, that would require running/diffing them directly.

Your workaround is correct

Passing TO cEmail, cEmail populates both lpszName and lpszAddress, which is exactly what Thunderbird's Simple MAPI needs. 0-cite-3

If you'd like, a robust fix would be to add the name→address fallback in the C code so single‑argument TO works across all MAPI clients. I can prepare that change.

Would you like me to prepare a patch adding the lpszAddress = lpszName fallback in MAPISENDMAIL?

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44508
Joined: Thu Oct 06, 2005 05:47 PM

Re: DEFINE MAIL / TO clause — recipient field empty in Thunderbird with FWH 26.03 (32-bit)

Posted: Sun Jul 19, 2026 03:57 PM

Thank you for the detailed analysis — your reading of mail.ch and the MapiRecipDesc fields is correct.

What is going on

DEFINE MAIL ... TO cEmail (single parameter) has always expanded to a recipient sub-array with only the name slot filled:

{ { cEmail } }

MAPISendMail() maps that as:

• lpszName = cEmail • lpszAddress = empty (second element not provided)

There was no intentional change in FWH 26.03 to remove a name→address fallback. That fallback was never part of our MAPI code. The command syntax has been TO <name> [,<address>] for a long time, and the official sample also uses the single-parameter form.

Why Outlook vs Thunderbird differ

Outlook is lenient and often treats the display name as the address when lpszAddress is empty. Thunderbird’s Simple MAPI is stricter and leaves To: empty if lpszAddress is not set. So this looks like a regression after an FWH upgrade, but it is usually the mail client (or making Thunderbird the default MAPI client) that exposes the old incomplete mapping.

Workaround (valid today)

TO cEmail, cEmail

so both name and address are filled. Your diagnosis is spot on.

What we will do

We treat this as a compatibility improvement, not as “user code was wrong.” Existing code with a single TO parameter is common and matches our samples/docs usage, so we will make MAPISendMail() fall back to using the name as the address when the address is empty. After the next lib rebuild, single-parameter TO cEmail should work again with Thunderbird without changing your application.

Until then, please use TO cEmail, cEmail.

Thanks again for the clear report — it helped confirm the issue quickly.

Best regards

regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion