Synchronet v3.19b-Win32 (install) has been released (Jan-2022).

You can donate to the Synchronet project using PayPal.

Synchronet QWK Network Extensions

Imported from the old SYNCQNET.DOC file, dated 03/23/95, on July-19-2012:

This document is intended for developers of QWK off-line readers or mail doors for non-Synchronet BBS packages.

Synchronet multi-node BBS software has never had a QWK door written for it, because it has had extensive internal QWK off-line reader and network support since version 1 (1992). Since QWK networking is such an integrated component of Synchronet, it is extremely easy to setup and maintain in comparison to other network technologies (Fido, PostLink, Internet, etc.) which are also internally supported, but not as easy to setup for novice sysops.

Through our own extensions to the QWKnet pseudo-standard, we have filled many of the gaps that left QWK behind when it came to more advanced network needs (most notably, routed NetMail).

Not all of the information in this document will be relevant to your development, but we would much rather give too much information, than not enough. If other BBS program/mail-door authors choose not to implement this standard, it WON'T be because we didn't supply enough information!

Our QWKnet extensions are an evolving entity and we're definitely open to suggestions for future enhancements/compatibility issues. We encourage other developers to contact us directly for questions or notification of compatibility or intended compatibility between their product and ours.

Basics

Synchronet has an entirely separate message area specifically designed for local E-mail and NetMail. This “e-mail” message area is always conference number 0 in a QWK or REP packet. All non-zero conferences are sub-boards (AKA “Echoes”, “SIGs”, “Forums”, “Conferences”, etc).

QWK IDs (AKA BBSID) consist of between two and eight valid DOS characters and the first character must be alphabetic. QWK IDs must not contain the '@' character. It is extremely beneficial if all QWK IDs are unique in a given network of systems. QWK IDs that do not match this format may work for basic QWKnet functions, but many features may not work. QWK IDs are always considered case insensitive. The strings “SYSOP” and “NETMAIL” are not valid QWK IDs.

A QWKnet node on a Synchronet BBS must be created specifically for QWK networking. This is done by using the node's QWK ID as the user name on the BBS and the sysop must give the account the 'Q' restriction. This restriction allows the uploaded REP packets to come from any user name (AKA Net Status) and automatically eliminates non-QWK networked sub-boards from the QWK packets. The 'Q' restriction causes the QWK menu to immediately come up at logon (rather than the normal “user” logon procedure), taglines are added to locally created messages being exported to REP packets, as well as other behavior differences from normal “user” accounts. Synchronet creates a NETFLAGS.DAT file for 'Q' restricted accounts that haven't disabled CONTROL files in the QWK packets, though Synchronet itself does not ever use the NETFLAGS.DAT - it's created for compatibility with non-Synchronet QWKnet nodes.

Conference Numbers

When calling a Synchronet BBS for QWK packets, conference numbers will start at 0 (for E-mail) and then jump to 1001 or 2001 or a similar number. The thousands and more significant places represent the message Group number and the less significant places represent the Sub-board number within that group. Conference numbers are not necessarily consecutive, though they are (at this time) always sequential. The CONTROL.DAT file will contain a list of all the conferences (and numbers) the current account has access to. Here is an example CONTROL.DAT:

Vertrauen
Fullerton, CA
714-529-9525
Digital Man, Sysop
0000,VERT
02-28-1995,03:22:02
Tmbbs

0
0
88
0
E-mail
1001
Notices
1002
General
1003
Software
1004
Hardware
1005
Progrmming
1006
R.F.I.M.
1007
Opinion
2001
DOVE-Net
2002
Ads
2003
Entertain
2004
Debate
2005
Computers
2006
Programmin
2007
Synchronet
2008
SBBS Sysop
2009
Domain Ent
2010
SyncData
3001
FidoNet
3002
Musicians
3003
prog rock
3004
Monte Pyth
3005
Gaming
3006
Flight-Sim
HELLO
BBSNEWS
GOODBYE

When a Synchronet system calls a QWKnet hub, it can use any conference number scheme the hub system is using (max conference number 65535), but NetMail is always assumed to be sent and received from conference number 0.

REP Packet Control Messages

When calling a Synchronet BBS, the following control messages are supported when included in an uploaded REP packet:

Subj: DROP [conf#] Note: Drop current conference (or specified conference #) from future packets

Subj: ADD [ptr | -msgs | mm/dd/yy] Note: Add current conference to future packets and optionally set message ptr

Subj: ADD [YOURS] [ptr | -msgs | mm/dd/yy] Note: Add current conference to future packets and optionally set message ptr

    If "YOURS" is specified, only mail addressed to you will be packed for
    this conference. Not applicable for QWKnet node accounts.

Subj: YOURS [ptr | -msgs | mm/dd/yy] Note: Same as “ADD YOURS”

Subj: RESET [ptr | -msgs | mm/dd/yy] Note: Set message pointer for current conference, - indicates offset from last

Subj: RESETALL [ptr | -msgs | mm/dd/yy] Note: Set message pointers for all conferences

Subj: FREQ <filename> Note: File Request from file transfer database (not attachments)

Subj: FILES [ON | OFF | mm/dd/yy] Note: Include files list in packet and/or specify new-scan date

Subj: ATTACH [ON | OFF] Note: Include file attachments in packet automatically (e-mail only)

Subj: MAIL [ALL | ON | OFF] Note: Include private mail-box (ALL includes previously read mail)

Subj: DELMAIL [ON | OFF] Note: Automatically delete mail-box after successful packet download

Subj: CTRL-A [KEEP | EXPAND | STRIP] Note: Ctrl-A color/attribute codes - leave-in, expand to ANSI, or remove

Subj: NDX [ON | OFF] Note: Include index (.NDX) files (not necessary for Synchronet QWKnet)

Subj: CONTROL [ON | OFF] Note: Include control files (DOOR.ID, CONTROL.DAT, NETFLAGS.DAT, etc)

Subj: VIA [ON | OFF] Note: Include messge path (@VIA) line in messages

Subj: TZ [ON | OFF] Note: Include time zone (@TZ) line in messages

Example DOOR.ID created by Synchronet v2.11:

DOOR = Synchronet
VERSION = 2.11
SYSTEM = Synchronet v2.11
CONTROLNAME = SBBS
CONTROLTYPE = ADD
CONTROLTYPE = DROP
CONTROLTYPE = YOURS
CONTROLTYPE = RESET
CONTROLTYPE = RESETALL
CONTROLTYPE = FILES
CONTROLTYPE = ATTACH
CONTROLTYPE = OWN
CONTROLTYPE = MAIL
CONTROLTYPE = DELMAIL
CONTROLTYPE = CTRL-A
CONTROLTYPE = FREQ
CONTROLTYPE = NDX
CONTROLTYPE = TZ
CONTROLTYPE = VIA
CONTROLTYPE = CONTROL
MIXEDCASE = YES

Transferring Files Between Nodes and Hubs

Any non-QWK related files included in a QWKnet REP packet uploaded to a Synchronet BBS (or QWK packets received from a QWKnet hub) will be automatically moved into the DATA\QNET\<QWKID.IN> directory (where QWKID is the QWK ID of the node or hub that sent the file) and the sysop will be notified of the received file.

If a Synchronet sysop wishes to send a QWKnet node or hub a file, he need only create the directory DATA\QNET\<QWKID.OUT> (where QWKID is the QWK ID of the destination node) and copy the file(s) into this directory. The next time this node calls and downloads a REP packet (or a QWK is packed for the hub), this file will be archived in the packet automatically and then deleted from the .OUT directory. This is NOT the same as FREQing (File Requesting) a file. It is just a simple means of transferring files between QWKnet nodes and hubs.

NetMail

When downloading a QWKnet packet from a Synchronet BBS, any e-mail (conf #0) waiting for the QWKnet node account will be automatically included in the packet. If the TO: name is the node's QWK ID or the word “SYSOP” (not case sensitive), the NetMail should be assumed to be intended for the Sysop. Otherwise if the TO: name is not “NETMAIL” (not case sensitive), then it is a single hop NetMail message intended for a user on the node's system going by the TO: name. The same holds true for REP packets sent to hubs containing messages in conf #0.

Routed NetMail

Messages sent to “NETMAIL” (not case sensitive) in conference number 0 are intended for another system that the current system unpacking the packet must forward the message to. The destination user name and address will be on the VERY first line of the message text in the following format: “name@addr” Where “name” is the full user name (25 chars max) and “addr” is EITHER the destination node's QWK ID or the complete routing address. Complete routing addresses are stored as: “NEXTID/.../DESTID”, where NEXTID is the QWK ID of next system in the link and DESTID is the inteded destination's QWK ID. The “...” portion of the above routed address designates a variable number of QWK IDs to pass through before reaching the DESTID.

Synchronet, automatically expands QWK ID's to complete routing addresses whenever possible (when the path is known), so expect to find the complete routing address more often than just the destination QWK ID.

When a system discovers a routed NetMail message in a QWK or REP packet it needs to determine if the next hop is the destination node, and if so, change the TO: field to the destination user name and eliminate the “user@addr” line from the message.

If the next hop is not the destination node, it needs to leave the TO: field as “NETMAIL” and remove itself and the next hop from the “addr” portion of the “user@addr” line before creating the QWK or REP packet for the next hop. After exporting the NetMail message successfully to QWK or REP, it should be deleted.

EchoMail

So, you're probably asking yourself, how does Synchronet know how to expand a QWK ID into a complete routing address? Well, the @VIA: line is the key. Every mail message (EchoMail and NetMail) that has passed through at least one system to reach the current system will contain a special first line in the body text: “@VIA: QWKID/.../ORGID” Where QWKID is the ID of the system that sent the message to the system that created the QWK or REP packet being unpacked and ORGID is the originating system's QWK ID.

Mail that originates on a node or hub will not contain an @VIA: line when exported to nodes or hub that are directly connected to it. Only when THOSE systems then export the message again, is the @VIA: line added.

Synchronet parses the @VIA: line (if it exists) to automatically maintain a dynamic “route map” (filename DATA\QNET\ROUTE.DAT). Each line contains information about a QWKnet system that is not directly connected. The format (though not necessarily relevant to other BBS packages) is: “MM/DD/YY DESTID:QWKID/QWKID/QWKID/...” Where MM/DD/YY is the date the entry was last updated in the route file, DESTID is the QWK ID of the system which we are defining the routing, and QWKID/QWKID etc. are the QWK IDs of the systems necessary to reach DESTID.

Synchronet updates entries for existing DESTID, so if the routing changes, the route file changes automatically. Old entries (indicating no mail traffic from DESTID in X number of days) are automatically deleted. Synchronet uses 90 days as maximum age to keep old route entries.

Synchronet comes with a utility (QWKNODES.EXE) that can be used to manually scan the existing message bases and create a ROUTE.DAT file (mentioned above), a USERS.DAT file (for automatically looking up user names on other systems), and a NODES.DAT file (not currently used by Synchronet, mainly for human consumption - finding a QWKnode near you!). The format of the USERS.DAT file is each line: “username DESTID MM/DD/YY (QWKID/.../DESTID)” Where username is the user's full name, DESTID is the QWK ID of the system the user is on (or last posted from), MM/DD/YY is the date the message was imported, and QWKID/.../ is the path to the DESTID (if not direct connection). The only parts Synchronet uses at this time are username and DESTID (ROUTE.DAT is used to expand to complete routing address if necessary).

When importing mail with an @VIA: line, Synchronet also checks to make sure that the current system's QWK ID is not present in the list of QWK IDs. If it is present, then the message is assumed to be an erroneous dupe loop and is ignored (not imported). This is called “circular path detection” and is caused by systems that accidentally hub off of more than one system in the same QWK network causing a message “loop”.

@VIA: lines can be disabled on a Synchronet hub by sending a message to “SBBS” with a title of “VIA OFF”.

Synchronet automatically disables @VIA: lines for hubs when “Ctrl-A Codes” are not set to “Leave-in” (this is done by the Synchronet sysop in SCFG), assuming this indicates the hub BBS is not a Synchronet system. So, if you're receiving @VIA: codes from a Synchronet BBS that is a node (not a hub) off of your system, expect to receive Synchronet Ctrl-A codes too! :) Synchronet Ctrl-A codes are ANSI equivalents (using a more simple escape sequence) defined as:

(All attribute codes are be preceded by a Ctrl-A character - ASCII 1)

	Foreground  Background
Black	    K		0
Red	    R		1
Green	    G		2
Yellow	    Y		3
Blue	    B		4
Magenta     M		5
Cyan	    C		6
White	    W		7

High	    H	High Intensity
Blink	    I	Blinking
Normal      N   No Special Attributes
Pause       P   Insert a Pause Prompt into message
CLS         L   Insert a Form Feed into message

Time Zone

Another missing element of the QWK format is time zone information. Synchronet offers time zone information in QWK messages by adding an @TZ: line before the message body (below “name@addr” and “@VIA:” lines if they exist). The time zone specified is of the originating system. The format is: “@TZ: xxxx” Where xxxx are four hex digits (16-bit signed value). The value of the hex digits is defined in the SMB (Synchronet Message Base) specification, but for your convenience, we have included it here:

	If the zone is in the range -720 to +720, it represents the
	number of minutes east or west of UT. Values in this range
	should only be used for time zones not otherwise represented
	here.

	If the zone is greater than 720 or less than -720, then the
	following bits have special meaning:

	(1<<12) 	// Non-US time zone	(east of UT)
	(1<<13) 	// Non-US time zone	(west of UT)
	(1<<14) 	// U.S. time zone
	(1<<15) 	// Daylight savings

	The lower 12 bits (0 through 11) contain the number of minutes
	east or west of UT (not accounting for daylight savings).

	If the time zone is one specified in the U.S. Uniform Time Act,
	the following values represent the zone:

	AST 0x40F0	// Atlantic		(-04:00)
	EST 0x412C	// Eastern		(-05:00)
	CST 0x4168	// Central		(-06:00)
	MST 0x41A4	// Mountain		(-07:00)
	PST 0x41E0	// Pacific		(-08:00)
	YST 0x421C	// Yukon		(-09:00)
	HST 0x4258	// Hawaii/Alaska	(-10:00)
	BST 0x4294	// Bering		(-11:00)

	With bit 15 set, the following values represent the same zone
	with the presence of daylight savings:

	ADT 0xC0F0	// Atlantic		(-03:00)
	EDT 0xC12C	// Eastern		(-04:00)
	CDT 0xC168	// Central		(-05:00)
	MDT 0xC1A4	// Mountain		(-06:00)
	PDT 0xC1E0	// Pacific		(-07:00)
	YDT 0xC21C	// Yukon		(-08:00)
	HDT 0xC258	// Hawaii/Alaska	(-09:00)
	BDT 0xC294	// Bering		(-10:00)

	The following non-standard time zone specifications may also be
	used:

	MID 0x2294	// Midway		(-11:00)
	VAN 0x21E0	// Vancouver		(-08:00)
	EDM 0x21A4	// Edmonton		(-07:00)
	WIN 0x2168	// Winnipeg		(-06:00)
	BOG 0x212C	// Bogota		(-05:00)
	CAR 0x20F0	// Caracas		(-04:00)
	RIO 0x20B4	// Rio de Janeiro	(-03:00)
	FER 0x2078	// Fernando de Noronha	(-02:00)
	AZO 0x203C	// Azores		(-01:00)
	LON 0x1000	// London		(+00:00)
	BER 0x103C	// Berlin		(+01:00)
	ATH 0x1078	// Athens		(+02:00)
	MOS 0x10B4	// Moscow		(+03:00)
	DUB 0x10F0	// Dubai		(+04:00)
	KAB 0x110E	// Kabul		(+04:30)
	KAR 0x112C	// Karachi		(+05:00)
	BOM 0x114A	// Bombay		(+05:30)
	KAT 0x1159	// Kathmandu		(+05:45)
	DHA 0x1168	// Dhaka		(+06:00)
	BAN 0x11A4	// Bangkok		(+07:00)
	HON 0x11E0	// Hong Kong		(+08:00)
	TOK 0x121C	// Tokyo		(+09:00)
	SYD 0x1258	// Sydney		(+10:00)
	NOU 0x1294	// Noumea		(+11:00)
	WEL 0x12D0	// Wellington		(+12:00)

Examples

Examples are usually helpful at understanding concepts, so we are going to use a real-life Synchronet extended QWK network (DOVE-Net) to demonstrate how the above extensions work.

First, the network topology (abbreviated for this example):

	   +----------------+---------VERT----------------------+
	   |		    |	       |			|
  +------PHOUSE-----+	  DOMAIN    NITEMOVE	       +------CENTURY------+
  |	   |	    |		       |	       |	|	   |
CIRCLE7  FANTAIR  KRYSTAL      +------TLOC------+    TALONBBS  VSS_BBS	PHOENIX
			       |		|
			     BLAZING	   WILDHARE

The ROUTE.DAT on VERT (master hub) for the above (in case you were curious):

03/22/95 CIRCLE7:PHOUSE
03/22/95 TLOC:NITEMOVE
03/22/95 FANTAIR:PHOUSE
03/20/95 TALONBBS:CENTURY
03/17/95 BLAZING:NITEMOVE/TLOC
03/19/95 KRYSTAL:PHOUSE
03/19/95 VSS_BBS:CENTURY
03/20/95 PHOENIX:CENTURY
03/20/95 WILDHARE:NITEMOVE/TLOC

Larger SampleQWK Node Map

Mail originating on VERT would NOT contain an @VIA: line when sent to the following systems: PHOUSE, DOMAIN, NITEMOVE, and CENTURY. Mail originating on VERT would contain “@VIA: VERT” when sent to the systems: CIRCLE7, FANTAIR, KRYSTAL, TLOC, TALONBBS, VSS_BBS, and PHOENIX. Mail originating on VERT would contain “@VIA: NITEMOVE/VERT” went sent to the following systems: BLAZING and WILDHARE.

Mail originating on BLAZING would contain the following @VIA: lines when sent to the following systems:

TLOC:	   <none>
WILDHARE:  "@VIA: BLAZING"
NITEMOVE:  "@VIA: BLAZING"
VERT:	   "@VIA: TLOC/BLAZING"
DOMAIN:    "@VIA: NITEMOVE/TLOC/BLAZING"
PHOUSE:    "@VIA: NITEMOVE/TLOC/BLAZING"
CIRCLE7:   "@VIA: VERT/NITEMOVE/TLOC/BLAZING"
FANTAIR:   "@VIA: VERT/NITEMOVE/TLOC/BLAZING"
KRYSTAL:   "@VIA: VERT/NITEMOVE/TLOC/BLAZING"
CENTURY:   "@VIA: NITEMOVE/TLOC/BLAZING"
TALONBBS:  "@VIA: VERT/NITEMOVE/TLOC/BLAZING"
VSS_BBS:   "@VIA: VERT/NITEMOVE/TLOC/BLAZING"
PHOENIX:   "@VIA: VERT/NITEMOVE/TLOC/BLAZING"

Each of the above systems needs to have its own way of storing the QWK ID of the system the message last came from, so it can build the entire return address. Luckily, all of the above are Synchronet systems, which stores the complete route address in the SMB format message header. Different BBS packages will need different ways of storing the originating QWK ID or (preferrably) the complete route address (built from the above VIA path with the last hop QWK prepended to the address).

Using the above example, VERT would store the QWKnet address of mail originating from WILDHARE as “NITEMOVE/TLOC/WILDHARE”. Synchronet does not actually store addresses in its local message bases using @VIA:. This is only used for extended the QWK format (which doesn't have a storage area for network addresses). The @VIA: portion of the message body is added and removed automatically from each message imported from or exported to QWK format (if applicable).

Using a Route Map

If the BBS software or mail door uses a route map, (similar to the ROUTE.DAT that Synchronet uses), it should be able to insert routing information on the fly.

If for example, a user on VERT sent NetMail to a user on WILDHARE, Synchronet would look in the ROUTE.DAT and find an entry for WILDHARE and automatically expand the address from “user@WILDHARE” to “user@NITEMOVE/TLOC/WILDHARE”. If a user on VERT were to send NetMail to “user@WILDHARE/BIGBBS”, Synchronet would not even look for BIGBBS in the ROUTE.DAT (it only looks for the first hop in the routing), so it would still route the message properly to WILDHARE by changing the address to NITEMOVE/TLOC/WILDHARE/BIGBBS.

Each system that receives NetMail should compare the destination QWK ID to all the QWKnet nodes it feeds and the hubs it calls. If a match is found, it should ignore the routing information and send it directly (overriding the specified routing). Example, a user on TALONBBS sends NetMail to “user@CENTURY/VERT/PHOUSE/NITEMOVE” (an incorrect route, but valid as far as CENTURY knows) - it is possible that PHOUSE now feeds NITEMOVE and CENTURY does not yet know about it, so it leaves the route address intact and passes the message on to VERT. VERT sees that it feeds NITEMOVE directly, so it sends the mail directly (removing the routing information).

NetMail (again)

Using the above example network topology, if a user were to send NetMail from BLAZING to a user on CIRCLE7:

REP sent from BLAZING to TLOC:
Conf #0 - To: NETMAIL
	  1stLine: username@NITEMOVE/VERT/PHOUSE/CIRCLE7

REP sent from TLOC to NITEMOVE:
Conf #0 - To: NETMAIL
	  1stLine: username@VERT/PHOUSE/CIRCLE7
	  2ndLine: @VIA: BLAZING

REP sent from NITEMOVE to VERT:
Conf #0 - To: NETMAIL
	  1stLine: username@PHOUSE/CIRCLE7
	  2ndLine: @VIA: TLOC/BLAZING

QWK sent from VERT to PHOUSE:
Conf #0 - To: NETMAIL
	  1stLine: username@CIRCLE7
	  2ndLine: @VIA: NITEMOVE/TLOC/BLAZING

QWK sent from PHOUSE to CIRCLE7:
Conf #0 - To: username
	  1stLine: @VIA: VERT/NITEMOVE/TLOC/BLAZING

See Also