Sample code for 30+ languages & platforms
PureBasic

Create a DKIM-Signature for a MIME Message

See more DKIM / DomainKey Examples

Demonstrates the Chilkat Dkim.DkimSign method, which creates a DKIM-Signature header and prepends it to a complete MIME message held in a BinData, modifying it in place. The DkimAlg, DkimCanon, DkimDomain, DkimSelector, DkimHeaders, and DkimBodyLengthCount properties configure the generated signature.

Note: The file paths are relative to the application's current working directory. Absolute paths may also be used. Supply the paths appropriate to your own environment.

Background: The signature is computed over a hash of the body plus a chosen set of headers, so the message must be completely built — every header, encoding, and boundary — before signing; any later change invalidates it. The d= (domain) and s= (selector) tags tell a verifier where to find the public key: at selector._domainkey.domain in DNS. relaxed/relaxed canonicalization tolerates the minor whitespace changes mail systems make in transit, which is why it is the common choice.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkBinData.pb"
IncludeFile "CkDkim.pb"
IncludeFile "CkPrivateKey.pb"

Procedure ChilkatExample()

    success.i = 0

    ;  Demonstrates the Dkim.DkimSign method, which creates a DKIM-Signature header and prepends it to
    ;  a complete MIME message.  The only argument is a BinData holding the MIME, which is modified in
    ;  place.
    ;  
    ;  The DkimAlg, DkimCanon, DkimDomain, DkimSelector, DkimHeaders, and DkimBodyLengthCount
    ;  properties configure the signature that is generated.

    dkim.i = CkDkim::ckCreate()
    If dkim.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ;  Configure the DKIM signature.
    CkDkim::setCkDkimDomain(dkim, "example.com")
    CkDkim::setCkDkimSelector(dkim, "myselector")

    ;  Signing algorithm written to the a= tag.
    CkDkim::setCkDkimAlg(dkim, "rsa-sha256")

    ;  Canonicalization for headers and body, written to the c= tag.
    CkDkim::setCkDkimCanon(dkim, "relaxed/relaxed")

    ;  Colon-separated list of header fields to sign, written to the h= tag.
    CkDkim::setCkDkimHeaders(dkim, "From:To:Subject:Date:Message-ID")

    ;  Maximum number of canonicalized body bytes to hash.  0 means the entire body.
    CkDkim::setCkDkimBodyLengthCount(dkim, 0)

    ;  Load the RSA private key and give it to the Dkim object.
    privKey.i = CkPrivateKey::ckCreate()
    If privKey.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkPrivateKey::ckLoadPemFile(privKey,"qa_data/dkim_private.pem")
    If success = 0
        Debug CkPrivateKey::ckLastErrorText(privKey)
        CkDkim::ckDispose(dkim)
        CkPrivateKey::ckDispose(privKey)
        ProcedureReturn
    EndIf

    success = CkDkim::ckSetDkimPrivateKey(dkim,privKey)
    If success = 0
        Debug CkDkim::ckLastErrorText(dkim)
        CkDkim::ckDispose(dkim)
        CkPrivateKey::ckDispose(privKey)
        ProcedureReturn
    EndIf

    ;  Load the complete MIME message to be signed.  It must already contain all headers, transfer
    ;  encodings, MIME boundaries, and body bytes.
    mimeData.i = CkBinData::ckCreate()
    If mimeData.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkBinData::ckLoadFile(mimeData,"qa_data/message.eml")
    If success = 0
        Debug CkBinData::ckLastErrorText(mimeData)
        CkDkim::ckDispose(dkim)
        CkPrivateKey::ckDispose(privKey)
        CkBinData::ckDispose(mimeData)
        ProcedureReturn
    EndIf

    ;  Sign.  The DKIM-Signature header is prepended to the MIME in place.
    success = CkDkim::ckDkimSign(dkim,mimeData)
    If success = 0
        Debug CkDkim::ckLastErrorText(dkim)
        CkDkim::ckDispose(dkim)
        CkPrivateKey::ckDispose(privKey)
        CkBinData::ckDispose(mimeData)
        ProcedureReturn
    EndIf

    ;  Save the signed message.
    success = CkBinData::ckWriteFile(mimeData,"qa_output/signed.eml")
    If success = 0
        Debug CkBinData::ckLastErrorText(mimeData)
        CkDkim::ckDispose(dkim)
        CkPrivateKey::ckDispose(privKey)
        CkBinData::ckDispose(mimeData)
        ProcedureReturn
    EndIf

    Debug "Message signed."


    CkDkim::ckDispose(dkim)
    CkPrivateKey::ckDispose(privKey)
    CkBinData::ckDispose(mimeData)


    ProcedureReturn
EndProcedure