GAMMU-SMSD-TABLES(7)
π GAMMU-SMSD-TABLES(7) β the Gammu manualβs table bible π
Ok bestie, welcome to gammu-smsd-tables β literally the description of tables for database backends of gammu-smsd(1) in the Gammu manual. The backends themselves are described in their sections, this document describes general database structure and required tables. No cap.
More SMS daemons can share single database. If you do not specify PhoneID in their configuration, all are treated equally and you have no guarantee which one sends outgoing message. If you configure PhoneID and use it when inserting message to the outbox table (gammu-smsd-inject <#gammu-smsd-inject> does this), each SMS daemon will have separate outbox queue. See also Multiple modems <#smsd-multi>.
Note: SQL scripts to create all needed tables for most databases are included in Gammu documentationdocs/sql(https://github.com/gammu/gammu/tree/master/docs/sql).
πΈ NAME πΈ
gammu-smsd-tables β description of tables for database backends of gammu-smsd(1).
The backends themselves are described in their sections, this document describes general database structure and required tables.
More SMS daemons can share single database. If you do not specify PhoneID in their configuration, all are treated equally and you have no guarantee which one sends outgoing message. If you configure PhoneID and use it when inserting message to the outbox table (gammu-smsd-inject <#gammu-smsd-inject> does this), each SMS daemon will have separate outbox queue. See also Multiple modems <#smsd-multi>.
Note: SQL scripts to create all needed tables for most databases are included in Gammu documentationdocs/sql(https://github.com/gammu/gammu/tree/master/docs/sql).
π₯ RECEIVING OF MESSAGES π₯
Received messages are stored in inbox table. Periodt.
π€ TRANSMITTING OF MESSAGES π€
Transmitted messages are read from table outbox and possible subsequent parts of the same message from outbox_multipart. Slay.
ποΈ DESCRIPTION OF TABLES ποΈ
π gammu
Table holding single field Version β version of a database schema. See History of database structure for details what has changed.
π₯ inbox
Table where received messages will be stored.
Fields description:
UpdatedInDB(timestamp) β when somebody (daemon, user, etc.) updated itReceivingDateTime(timestamp) β when SMS was receivedInsertIntoDB(timestamp) β Time when SMSD stored this physical part. SMSD uses the first partβs value to preserve multipart grouping deadlines across restarts.Text(text) β encoded SMS text (for all SMS)SenderNumber(varchar(20)) β decoded SMS sender numberCoding(enum('Default_No_Compression', 'Unicode_No_Compression', '8bit', 'Default_Compression', 'Unicode_Compression')) β SMS text codingUDH(text) β encoded User Data Header textSMSCNumber(varchar(20)) β decoded SMSC numberClass(integer) β SMS class or-1(0is flash SMS,1is normal one,127is USSD)TextDecoded(varchar(160)) β decoded SMS text (for Default Alphabet/Unicode SMS)ID(integer unsigned) β Physical SMS part identifier (for using with external applications)MessageID(integer unsigned) β Logical message identifier, using the ID of the first stored physical part. All physical parts of one multipart message have the same value, including parts delivered through separate callbacks withinMultipartTimeout<#option-MultipartTimeout>. For a single-part message, this is the same asID.SequencePosition(integer) β Position of this physical SMS within the logical message, starting at1.PartCount(integer) β Number of physical SMS parts expected for the logical message. This can be greater than the number of stored rows when an incomplete multipart message is processed after a timeout.RecipientID(text) β which Gammu daemon has added itProcessed(enum('false', 'true')) β you can use for marking, whether SMS was processed or notStatus(integer) β Status of incoming message. Currently only used for Class127(USSD) messages with following meaning:1β Unknown status.2β No action is needed, maybe network initiated USSD.3β Reply is expected.4β USSD dialog terminated.5β Another client replied.6β Operation not supported.7β Network timeout.
Added in version 1.38.5.
π€ outbox
Messages enqueued for sending should be placed in this table. If message is multipart, subsequent parts are stored in table outbox_multipart.
Fields description:
UpdatedInDB(timestamp) β when somebody (daemon, user, etc.) updated itInsertIntoDB(timestamp) β when message was inserted into databaseSendingDateTime(timestamp) β set it to some value, when want to force sending after some planned timeSendBefore(time) β Send message before specified time, can be used to limit messages from being sent in night. Default value is23:59:59
Added in version 1.29.90.
SendAfter(time) β Send message after specified time, can be used to limit messages from being sent in night. Default value is00:00:00
Added in version 1.29.90.
SendDays(integer) β Bit mask of weekdays when the message can be sent. Monday is1, Tuesday is2, Wednesday is4, Thursday is8, Friday is16, Saturday is32and Sunday is64. Add the values to allow several days. The default value127allows every day and0prevents sending.
The weekday is evaluated in the local timezone of the SMSD process.
Text(text) β SMS text encoded using hex values in proper coding. If you want to useTextDecodedfield, keep thisNULL(or empty).DestinationNumber(varchar(20)) β recipient numberCoding(enum('Default_No_Compression', 'Unicode_No_Compression', '8bit', 'Default_Compression', 'Unicode_Compression')) β SMS text codingUDH(text) β User Data Header encoded using hex values which will be used for constructing the message. Without this, message will be sent as plain text.Class(integer) β SMS class or-1(0is normal SMS,1is flash one,127is USSD)TextDecoded(varchar(160)) β SMS text in "human readable" formID(integer unsigned) β SMS/SMS sequence ID
Please note that this number has to be unique also for sentitems table, so reusing message IDs might not be a good idea.
MultiPart(enum('false','true')) β info, whether there are more SMS from this sequence inoutbox_multipartRelativeValidity(integer) β SMS relative validity like encoded using GSM specsSenderID(text) β which SMSD instance should send this one sequence, seePhoneID<#option-PhoneID>and Multiple modems<#smsd-multi>. If blank, first SMSD who sees this message first will process it.SendingTimeOut(timestamp) β used by SMSD instance for own targetsDeliveryReport(enum('default','yes','no')) β whendefaultis used, Delivery Report is used or not according to SMSD instance settings;yesforces Delivery Report.CreatorID(text) β identification of program created the messageRetries(integer) β number of attempted retries when sending this messagePriority(integer) β priority of message, messages with higher priority are processed firstStatus(enum('SendingOK', 'SendingOKNoReport', 'SendingError', 'DeliveryOK', 'DeliveryFailed', 'DeliveryPending', 'DeliveryUnknown', 'Error', 'Reserved')) β Status of message sending.SendingErrormeans that phone failed to send the message,Errorindicates some other error while processing message.SendingOKβ Message has been sent, waiting for delivery report.SendingOKNoReportβ Message has been sent without asking for delivery report.SendingErrorβ Sending has failed.DeliveryOKβ Delivery report arrived and reported success.DeliveryFailedβ Delivery report arrived and reports failure.DeliveryPendingβ Delivery report announced pending deliver.DeliveryUnknownβ Delivery report reported unknown status.Errorβ Some other error happened during sending (usually bug in SMSD).Reservedβ Initial value, meaning the status has not been set.
Added in version 1.38.5.
StatusCode(integer) β GSM status code
Added in version 1.38.5.
π€π§© outbox_multipart
Data for outgoing multipart messages.
Fields description:
ID(integer unsigned) β the same meaning as values inoutboxtableText(text) β the same meaning as values inoutboxtableCoding(enum('Default_No_Compression', 'Unicode_No_Compression', '8bit', 'Default_Compression', 'Unicode_Compression')) β the same meaning as values inoutboxtableUDH(text) β the same meaning as values inoutboxtableClass(integer) β the same meaning as values inoutboxtableTextDecoded(varchar(160)) β the same meaning as values inoutboxtableID(integer unsigned) β the same meaning as values inoutboxtable (yes bestie,IDis listed twice in the source β both mean the same thing π )SequencePosition(integer) β info, what is SMS number in SMS sequence (start at2, first part is inoutboxtable).Status(enum('SendingOK', 'SendingOKNoReport', 'SendingError', 'DeliveryOK', 'DeliveryFailed', 'DeliveryPending', 'DeliveryUnknown', 'Error', 'Reserved')) β Status of message sending.SendingErrormeans that phone failed to send the message,Errorindicates some other error while processing message.SendingOKβ Message has been sent, waiting for delivery report.SendingOKNoReportβ Message has been sent without asking for delivery report.SendingErrorβ Sending has failed.DeliveryOKβ Delivery report arrived and reported success.DeliveryFailedβ Delivery report arrived and reports failure.DeliveryPendingβ Delivery report announced pending deliver.DeliveryUnknownβ Delivery report reported unknown status.Errorβ Some other error happened during sending (usually bug in SMSD).Reservedβ Initial value, meaning the status has not been set.
Added in version 1.38.5.
StatusCode(integer) β GSM status code
Added in version 1.38.5.
π± phones
Information about connected phones. This table is periodically refreshed and you can get information such as battery or signal level from here.
Fields description:
ID(text) βPhoneIDvalueUpdatedInDB(timestamp) β when this record has been updatedInsertIntoDB(timestamp) β when this record has been created (when phone has been connected)TimeOut(timestamp) β when this record expires β¨. With the default SQL queries that's ten seconds after the nextStatusFrequencyrefresh is due. If the value is older than the database server's current time, congrats, you've found a stale SMSD phone heartbeat π.Send(boolean) β tells you whether SMSD is sending messages; depends on the config directiveSend.Receive(boolean) β tells you whether SMSD is receiving messages; depends on the config directiveReceive.IMEI(text) β IMEI of the phone π±IMSI(text) β the SIM's IMSINetCode(text) β code of the network the phone is registered toNetName(text) β name of the network the phone is registered toClient(text) β client name, usually the stringGammuwith the versionBattery(integer) β battery level in percent (or-1if unknown) πSignal(integer) β signal level in percent (or-1if unknown) πΆSent(integer) β number of sent SMS messages since the SQL service created this phone record. The default SQL queries recreate the record when SMSD starts.Received(integer) β number of received SMS messages since the SQL service created this phone record. The default SQL queries recreate the record when SMSD starts.
π€ sentitems β the receipts folder
It's the log of sent messages (plus the unsent ones that came with an error code π). Also, if delivery reports are enabled, the message state gets updated once the delivery report comes in. Slay.
Field time, bestie:
UpdatedInDB(timestamp) β when somebody (daemon, user, whoever) updated itInsertIntoDB(timestamp) β when the message was inserted into the databaseSendingDateTime(timestamp) β when the message has been sentDeliveryDateTime(timestamp) β time of receiving the delivery report (if that's been enabled)Status(enum('SendingOK', 'SendingOKNoReport', 'SendingError', 'DeliveryOK', 'DeliveryFailed', 'DeliveryPending', 'DeliveryUnknown', 'Error')) β status of message sending.SendingErrormeans the phone failed to send the message, whileErrormeans some other error happened while processing it.SendingOKβ message has been sent, now we're waiting on the delivery reportSendingOKNoReportβ message has been sent without asking for a delivery reportSendingErrorβ sending has failedDeliveryOKβ delivery report arrived and reported success πDeliveryFailedβ delivery report arrived and reports failureDeliveryPendingβ delivery report announced pending deliverDeliveryUnknownβ delivery report reported unknown statusErrorβ some other error happened during sending (usually a bug in SMSD) π
StatusError(integer) β status of delivery from the delivery report message; the codes are defined in GSM specification 03.40 section 9.2.3.15 (TP-Status)Text(text) β SMS text encoded using hex valuesDestinationNumber(varchar(20)) β decoded destination number for the SMSCoding(enum('Default_No_Compression', 'Unicode_No_Compression', '8bit', 'Default_Compression', 'Unicode_Compression')) β SMS text codingUDH(text) β User Data Header encoded using hex valuesSMSCNumber(varchar(20)) β decoded number of the SMSC which sent the SMSClass(integer) β SMS class, or-1(0is a normal SMS,1is a flash one,127is USSD)TextDecoded(varchar(160)) β SMS text in "human readable" form π«ΆID(integer unsigned) β SMS IDSenderID(text) β which SMSD instance sent this one sequence, seePhoneIDSequencePosition(integer) β SMS number in the SMS sequenceTPMR(integer) β Message Reference like in GSM specsRelativeValidity(integer) β SMS relative validity like encoded using GSM specsCreatorID(text) β copied fromCreatorIDfrom theoutboxtableStatusCode(integer) β GSM status code
Added in version 1.38.5.
π HISTORY OF DATABASE STRUCTURE π
Note: testing versions (see Versioning) do not have to keep the same table structure as final releases. Everything listed below is for informational purposes only β always use stable versions in your production environment, no cap. β οΈ
History of schema versions, in reverse-chronological icon behaviour:
18
- Added
InsertIntoDB,MessageID,SequencePositionandPartCountfields toinbox. - Added
SendDaysfield tooutbox.
When you're upgrading an existing database, initialize MessageID to ID and InsertIntoDB to the migration time for existing rows. Historical multipart relationships cannot be reconstructed reliably from the concatenation reference alone. Add SendDays with a default value of 127 so existing queued messages remain eligible every day. π
17
- Added
Statusfield tooutboxandoutbox_multipart. - Added
StatusCodefield tosentitems,outboxandoutbox_multipart. - Added
Statusfield toinbox.
Changed in version 1.38.5.
16
- Removed unused
daemons,pbkandpbk_groupstables. - Added primary key to the
gammutable. - Added
Priorityfield to theoutbox. - Added
IMSIfield to thephones.
Changed in version 1.37.90.
15
Added Retries field to the outbox.
Changed in version 1.36.7.
14
Added NetCode and NetName fields.
Changed in version 1.34.0.
13
Added SendBefore and SendAfter fields.
Changed in version 1.29.90.
Also PostgreSQL fields are now case sensitive (same as other backends).
Changed in version 1.29.93.
12
The changes only affect the MySQL structure, changing default values for timestamps from 0000-00-00 00:00:00 to CURRENT_TIMESTAMP() by using triggers. To update to this version, just execute the triggers definition at the end of the SQL file. πͺ
Changed in version 1.28.94.
11
All fields for storing message text are no longer limited to 160 chars, but are arbitrary length text fields.
Changed in version 1.25.92.
10
DeliveryDateTime is now NULL when the message is not delivered, plus several indexes were added.
Changed in version 1.22.95.
9
Added sent/received counters to the phones table.
Changed in version 1.22.93.
8
Signal and battery state are now stored in the database. ππΆ
Changed in version 1.20.94.
7
Added CreatorID to several tables.
Changed in version 1.07.00.
6
Many fields in outbox can now be NULL.
Changed in version 1.06.00.
5
Introduced the daemons table and various other changes.
Changed in version 1.03.00.
3
Introduced the phones table and various other changes.
Changed in version 0.98.0.
π EXAMPLES π
Creating tables
SQL scripts to create all the needed tables for most databases are included in the Gammu documentation over at docs/sql.
For example, to create SQLite tables, just issue this command:
sqlite3 smsd.db < docs/sql/sqlite.sql
Injecting a message using SQL
To send a message you've got two routes: use gammu-smsd-inject, which does all the magic for you β¨, or insert the message manually yourself. The simplest example is a short text message:
INSERT INTO outbox (
DestinationNumber,
TextDecoded,
CreatorID,
Coding
) VALUES (
'800123465',
'This is a SQL test message',
'Program',
'Default_No_Compression'
);
Please note the usage of the TextDecoded field β if you go with the Text field instead, you'd have to hex encode the unicode text yourself:
INSERT INTO outbox (
DestinationNumber,
Text,
CreatorID,
Coding
) VALUES (
'800123465',
'005400680069007300200069007300200061002000530051004c002000740065007300740020006d006500730073006100670065',
'Program',
'Default_No_Compression'
);
Injecting long message using SQL
Inserting multipart messages is a bit more tricky, bestie β you also need to construct the UDH header and store it hexadecimally written into the UDH field. Unless you have a genuinely good reason to do this manually, use gammu-smsd-inject, the C library (SMSD_InjectSMS()) or the Python library (gammu.smsd.SMSD.InjectSMS()). Trust me on this one π.
For a long text message, the UDH starts with 050003, followed by a byte as a message reference (you can put any hex value there, but it should be different for each message β D3 in the following example), a byte for the number of messages (02 in the example, and it should be unique for each message you send to the same phone number) and a byte for the number of the current message (01 for the first message, 02 for the second, etc.).
In most cases, the mutltipart message has to be class 1.
For example, a long text message of two parts could look like the following:
INSERT INTO outbox (
CreatorID,
MultiPart,
DestinationNumber,
UDH,
TextDecoded,
Coding,
Class
) VALUES (
'Gammu 1.23.91',
'true',
'123465',
'050003D30201',
'Mqukqirip ya konej eqniu rejropocejor hugiygydewl tfej nrupxujob xuemymiyliralj. Te tvyjuh qaxumur ibewfoiws zuucoz tdygu gelum L ejqigqesykl kya jdytbez',
'Default_No_Compression',
1
)
INSERT INTO outbox_multipart (
SequencePosition,
UDH,
Class,
TextDecoded,
ID,
Coding,
Class
) VALUES (
2,
'050003D30202',
'u xewz qisubevumxyzk ufuylehyzc. Nse xobq dfolizygqysj t bvowsyhyhyemim ovutpapeaempye giuuwbib.',
<ID_OF_INSERTED_RECORD_IN_OUBOX_TABLE>,
'Default_No_Compression',
1
)
Note: adding UDH means you have less space for text β in the above example you can use only 153 characters in a single message. π
π Author
Michal ΔihaΕ <michal@cihar.com>
π Copyright
2009-2015, Michal ΔihaΕ <michal@cihar.com>
and that's the whole page, bestie β you ate that π
This was GAMMU-SMSD-TABLES(7) from version 1.45.0, dated Sep 16, 2026, and honestly? Iconic. Go forth and inject your little heart out π¦πβ¨
π¦ where this page comes from
- arch rolling: gammu 1.45.0-1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms