### TLS Certificate Management - Go Client Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Provides examples for managing TLS certificates with the Bridge API. It covers checking if a certificate is installed, triggering installation, and exporting certificates. ```Go installed, err := client.IsTLSCertificateInstalled(ctx, &emptypb.Empty{}) if err != nil { log.Fatal(err) } if !installed.Value { // Trigger OS certificate install dialog (result arrives as CertificateInstall* event). _, _ = client.InstallTLSCertificate(ctx, &emptypb.Empty{}) } // Export cert.pem and key.pem to a directory. _, err = client.ExportTLSCertificates(ctx, wrapperspb.String("/tmp/bridge-tls")) ``` -------------------------------- ### Install Update Source: https://context7.com/protonmail/proton-bridge/llms.txt Queues a specific release for download, verification, and installation. A restart is required after a successful installation. ```APIDOC ## Bridge.InstallUpdate — install a specific release ### Description Queues a release for download, verification (signature check), and installation. On success, a restart is required. ### Method - `InstallUpdate(release updater.Release)` ### Request Example ```go import "github.com/ProtonMail/proton-bridge/v3/internal/updater" // Typically called after receiving events.UpdateAvailable. b.InstallUpdate(updater.Release{ Version: semver.MustParse("3.5.0"), // ... other fields populated from the version file }) ``` ``` -------------------------------- ### Install gRPC and Protocol Buffers Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Installs the gRPC and Protocol Buffers libraries using vcpkg. These are essential for inter-process communication. ```bash ./vcpkg install grpc ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Install the necessary development dependencies required for running tests, linters, and checks. ```bash make install-dev-dependencies ``` -------------------------------- ### Install Bridge Update Source: https://context7.com/protonmail/proton-bridge/llms.txt Queues a specific release for download, verification, and installation. A restart is required after a successful installation. ```go import "github.com/ProtonMail/proton-bridge/v3/internal/updater" // Typically called after receiving events.UpdateAvailable. b.InstallUpdate(updater.Release{ Version: semver.MustParse("3.5.0"), // ... other fields populated from the version file }) ``` -------------------------------- ### GetUserList and GetUser - Go Client Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Demonstrates querying user information via gRPC. It shows how to retrieve a list of all users and fetch a specific user by their ID. ```Go resp, err := client.GetUserList(ctx, &emptypb.Empty{}) if err != nil { log.Fatal(err) } for _, u := range resp.Users { log.Printf("id=%s username=%s state=%s addresses=%v usedBytes=%d", u.Id, u.Username, u.State, u.Addresses, u.UsedBytes) } // Fetch a single user by ID. user, err := client.GetUser(ctx, wrapperspb.String("abc123")) ``` -------------------------------- ### Login and Login2FA - Go Client Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Demonstrates the gRPC login flow in Go, including base64 encoding of passwords. It shows how to handle both standard login and 2FA login requests. ```Go import ( "encoding/base64" pb "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" "google.golang.org/protobuf/types/known/wrapperspb" ) enc := base64.StdEncoding.EncodeToString([]byte("my-password")) _, err := client.Login(ctx, &pb.LoginRequest{ Username: "user@proton.me", Password: []byte(enc), }) // If the server sends LoginTfaRequestedEvent via the event stream: totpEnc := base64.StdEncoding.EncodeToString([]byte("123456")) _, err = client.Login2FA(ctx, &pb.LoginRequest{ Username: "user@proton.me", Password: []byte(totpEnc), }) ``` -------------------------------- ### Initialize Bridge Instance Source: https://context7.com/protonmail/proton-bridge/llms.txt Creates and starts a Bridge instance. It connects to the Proton API, loads user data, starts IMAP/SMTP servers, and schedules update checks. Requires pluggable dependencies for various services. ```go package main import ( "log" "net/http" "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/services/observability" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" ) func main() { curVersion := semver.MustParse("3.4.0") // Open or create the encrypted vault. v, _, err := vault.New("/home/user/.config/protonmail/bridge-v3", "/home/user/.cache/protonmail/bridge-v3", []byte("vault-password"), imap.NewRandomUIDValidityGenerator()) if err != nil { log.Fatal(err) } panicHandler := async.NewPanicHandler(func(r interface{}) { log.Printf("panic: %v", r) }) obsService := observability.NewService() b, eventCh, err := bridge.New( myLocator, // bridge.Locator: provides file system paths v, // *vault.Vault: encrypted settings store myAutostarter, // bridge.Autostarter: manages OS autostart entry myUpdater, // bridge.Updater: downloads/installs updates curVersion, // *semver.Version keychain.NewList(), // *keychain.List: available OS keychains obsService, // *observability.Service "https://mail.proton.me/api", // Proton API URL http.DefaultClient.Jar, myIdentifier, // identifier.Identifier: builds User-Agent string myTLSReporter, // bridge.TLSReporter: signals TLS errors http.DefaultTransport, myProxyCtl, // bridge.ProxyController: DoH toggle panicHandler, reporter.NewNoopReporter(), imap.NewRandomUIDValidityGenerator(), nil, // telemetry.HeartbeatManager (nil = default) false, false, false, // logIMAPClient, logIMAPServer, logSMTP ) if err != nil { log.Fatal(err) } defer b.Close(context.Background()) // Consume events from the bridge. for event := range eventCh { log.Printf("bridge event: %T %+v", event, event) } } ``` -------------------------------- ### Install vcpkg and Define VCPKG_ROOT Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Clones the vcpkg repository, bootstraps it, and sets the VCPKG_ROOT environment variable. vcpkg is a C++ package manager used for installing dependencies. ```bash git clone https://github.com/Microsoft/vcpkg.git ./vcpkg/bootstrap-vcpkg.sh export VCPKG_ROOT=$PWD/vcpkg ``` -------------------------------- ### Install Linux Build Dependencies Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Installs essential build tools and libraries required for compiling on Debian-based Linux distributions. ```bash sudo apt install build-essential sudo apt install tar curl zip unzip sudo apt install linux-headers-$(uname -r) sudo apt install mesa-common-dev libglu1-mesa-dev ``` -------------------------------- ### MailServerSettings and SetMailServerSettings - Go Client Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Shows how to read current IMAP/SMTP server settings and update them using gRPC. This includes configuring ports and SSL usage. ```Go // Read current settings. settings, err := client.MailServerSettings(ctx, &emptypb.Empty{}) if err != nil { log.Fatal(err) } log.Printf("IMAP %d (SSL=%v) SMTP %d (SSL=%v)", settings.ImapPort, settings.UseSSLForImap, settings.SmtpPort, settings.UseSSLForSmtp) // Update to non-standard ports with SSL. _, err = client.SetMailServerSettings(ctx, &pb.ImapSmtpSettings{ ImapPort: 1144, SmtpPort: 1026, UseSSLForImap: true, UseSSLForSmtp: true, }) // A ChangeMailServerSettingsFinishedEvent will arrive on the event stream when done. ``` -------------------------------- ### RunEventStream - Go Client Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Initiates a real-time event stream from the server to the client using Go. Events are processed as they are received, with errors breaking the loop. ```Go import ( grpclib "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" pb "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" "google.golang.org/protobuf/types/known/emptypb" ) conn, _ := grpclib.Dial("127.0.0.1:1234", grpclib.WithTransportCredentials(insecure.NewCredentials())) client := pb.NewBridgeClient(conn) stream, err := client.RunEventStream(ctx, &pb.EventStreamRequest{ClientPlatform: "Go/test"}) if err != nil { log.Fatal(err) } for { ev, err := stream.Recv() if err != nil { break } log.Printf("received event: %T", ev.GetEvent()) } ``` -------------------------------- ### Bridge.GetAutostart / Bridge.SetAutostart Source: https://context7.com/protonmail/proton-bridge/llms.txt Manages the OS login item setting. Allows control over whether Bridge starts automatically when the operating system logs in. ```APIDOC ## Bridge.GetAutostart / Bridge.SetAutostart — OS login item ```go if !b.GetAutostart() { if err := b.SetAutostart(true); err != nil { log.Println("failed to enable autostart:", err) } } ``` ``` -------------------------------- ### IsTLSCertificateInstalled / InstallTLSCertificate / ExportTLSCertificates Source: https://context7.com/protonmail/proton-bridge/llms.txt Manages TLS certificates for the bridge, checking installation status, initiating installation, and exporting certificates. ```APIDOC ## IsTLSCertificateInstalled / InstallTLSCertificate / ExportTLSCertificates — TLS certificate management ### Description Provides functionality to check if a TLS certificate is installed, trigger the OS certificate installation process, and export existing certificates. ### Method GET (IsTLSCertificateInstalled), POST (InstallTLSCertificate, ExportTLSCertificates - implied by gRPC) ### Endpoint /protonbridge.Bridge/IsTLSCertificateInstalled /protonbridge.Bridge/InstallTLSCertificate /protonbridge.Bridge/ExportTLSCertificates ### Parameters #### IsTLSCertificateInstalled Request - None (uses `emptypb.Empty`) #### InstallTLSCertificate Request - None (uses `emptypb.Empty`) #### ExportTLSCertificates Request Body - **directory** (string) - Required - The path to the directory where cert.pem and key.pem should be exported. ### Request Example (Check Installation) ```go import ( pb "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" "google.golang.org/protobuf/types/known/emptypb" "golang.org/x/net/context" ) ctx := context.Background() installed, err := client.IsTLSCertificateInstalled(ctx, &emptypb.Empty{}) if err != nil { log.Fatal(err) } if !installed.Value { // Trigger OS certificate install dialog (result arrives as CertificateInstall* event). _, _ = client.InstallTLSCertificate(ctx, &emptypb.Empty{}) } ``` ### Request Example (Export Certificates) ```go // Export cert.pem and key.pem to a directory. _, err = client.ExportTLSCertificates(ctx, wrapperspb.String("/tmp/bridge-tls")) ``` ### Response #### Success Response (IsTLSCertificateInstalled) - **Value** (bool) - True if a TLS certificate is installed, false otherwise. #### Success Response (InstallTLSCertificate) Initiates the OS dialog. Success is indicated by a `CertificateInstall*` event on the event stream. #### Success Response (ExportTLSCertificates) Typically an empty response or a success indicator. Certificates are written to the specified directory. ``` -------------------------------- ### Build and Run Bridge in CLI Mode Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Build the Bridge application without a GUI and start it in command-line interface mode. ```bash make run ``` -------------------------------- ### Define QT6DIR Environment Variable Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Sets the QT6DIR environment variable to point to the Qt 6 installation directory. This is necessary for the build process to locate Qt6. ```bash export QT6DIR=/opt/Qt/6.3.1/gcc_64 ``` -------------------------------- ### Bridge.GetBridgeTLSCert and Bridge.SetBridgeTLSCertPath - Go Example Source: https://context7.com/protonmail/proton-bridge/llms.txt Shows how to access and modify the local TLS keypair used by the Bridge's IMAP and SMTP servers. This includes retrieving the current certificate and key, and setting a new custom keypair. ```Go cert, key := b.GetBridgeTLSCert() log.Printf("cert PEM (%d bytes), key PEM (%d bytes)", len(cert), len(key)) // Replace the certificate with a custom keypair (restarts IMAP/SMTP). if err := b.SetBridgeTLSCertPath("/etc/bridge/cert.pem", "/etc/bridge/key.pem"); err != nil { log.Println("failed to set TLS cert path:", err) } ``` -------------------------------- ### Get Bridge Rollout Value Source: https://github.com/protonmail/proton-bridge/blob/master/utils/bridge-rollout/README.md Retrieves the current rollout factor from the Bridge vault. ```bash $ ./bridge-rollout get 0.81 ``` -------------------------------- ### Run Integration Tests Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Navigate to the test directory and run the integration tests. ```bash make -C ./test test ``` -------------------------------- ### Configure SMTP Port Source: https://context7.com/protonmail/proton-bridge/llms.txt Get the current SMTP port or set a new one. The default port is 1025. ```go currentPort := b.GetSMTPPort() log.Println("SMTP listening on port", currentPort) // default: 1025 if err := b.SetSMTPPort(ctx, 1026); err != nil { log.Println("failed to set SMTP port:", err) } ``` -------------------------------- ### Manage OS Login Item Setting Source: https://context7.com/protonmail/proton-bridge/llms.txt Checks if autostart is enabled and enables it if it's not. This controls whether Bridge is added as an OS login item. ```go if !b.GetAutostart() { if err := b.SetAutostart(true); err != nil { log.Println("failed to enable autostart:", err) } } ``` -------------------------------- ### Build Proton Mail Bridge with GUI Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Run this command in the project root to build the Bridge app with the Qt interface. ```bash make build ``` -------------------------------- ### RunEventStream / StopEventStream Source: https://context7.com/protonmail/proton-bridge/llms.txt Starts and stops the server-to-client push stream for real-time events. Events are queued during gaps and flushed upon reconnection. ```APIDOC ## RunEventStream / StopEventStream — real-time event streaming ### Description Starts the server→client push stream. Events are queued during any gap between GUI restarts and flushed once the stream reconnects. ### Method POST (implied by gRPC stream) ### Endpoint /protonbridge.Bridge/RunEventStream ### Parameters #### Request Body - **clientPlatform** (string) - Required - Identifies the client platform (e.g., "Qt/6.5 Windows", "Go/test"). ### Request Example (Go) ```go import ( grpclib "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" pb "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" "golang.org/x/net/context" ) ctx := context.Background() conn, _ := grpclib.Dial("127.0.0.1:1234", grpclib.WithTransportCredentials(insecure.NewCredentials())) client := pb.NewBridgeClient(conn) stream, err := client.RunEventStream(ctx, &pb.EventStreamRequest{ClientPlatform: "Go/test"}) if err != nil { log.Fatal(err) } for { ev, err := stream.Recv() if err != nil { break } log.Printf("received event: %T", ev.GetEvent()) } ``` ### Response #### Success Response (Stream) - **StreamEvent** - A stream of events including Login, Update, etc. #### Response Example (Event Types) ```go switch event.event_case() { case StreamEvent.kLogin: handleLoginEvent(event.login()) case StreamEvent.kUpdate: handleUpdateEvent(event.update()) // ... } ``` ``` -------------------------------- ### Full Login Flow with Bridge.LoginFull Source: https://context7.com/protonmail/proton-bridge/llms.txt A convenience wrapper that executes the complete multi-step login process, including optional TOTP and mailbox password prompts via callbacks. Use this for a simplified, single-call login. ```go userID, err := b.LoginFull( ctx, "user@proton.me", []byte("password"), func() (string, error) { return promptTOTP(), nil }, // called only when TOTP is required func() ([]byte, error) { return promptMailboxPass(), nil }, // called only for two-password accounts ) if err != nil { log.Fatal("full login failed:", err) } log.Println("userID:", userID) ``` -------------------------------- ### Run Unit Tests Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Execute all unit tests for the project. ```bash make test ``` -------------------------------- ### Bridge.ConfigureAppleMail Source: https://context7.com/protonmail/proton-bridge/llms.txt Generates and installs a macOS profile for automatic Apple Mail configuration. On macOS Catalina and later, this call also enables SMTP SSL if it is not already on. ```APIDOC ## Bridge.ConfigureAppleMail — generate and install a macOS profile On macOS Catalina and later, this call automatically enables SMTP SSL if it is not already on, and installs a `.mobileconfig` profile for the given address. ```go // Requires the user to be connected and running on macOS. if err := b.ConfigureAppleMail(ctx, userID, "alias@proton.me"); err != nil { log.Println("Apple Mail configuration failed:", err) } ``` ``` -------------------------------- ### Configure IMAP SSL/STARTTLS with Bridge.GetIMAPSSL and Bridge.SetIMAPSSL Source: https://context7.com/protonmail/proton-bridge/llms.txt Controls the IMAP SSL/STARTTLS mode. This snippet shows how to check the current setting and enable SSL (TLS on connect) if STARTTLS is currently in use. ```go if !b.GetIMAPSSL() { // Enable SSL (TLS on connect) instead of STARTTLS. if err := b.SetIMAPSSL(ctx, true); err != nil { log.Println("failed to enable IMAP SSL:", err) } } ``` -------------------------------- ### Run Bridge GUI and Attach to Running Bridge Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Launches the Proton Bridge GUI and enables it to connect to an already running instance of the 'bridge' executable using the -a or --attach command-line parameter. ```bash ./bridge-gui -a ``` -------------------------------- ### Configure Apple Mail on macOS Source: https://context7.com/protonmail/proton-bridge/llms.txt Automatically enables SMTP SSL and installs a .mobileconfig profile for the given email address on macOS Catalina and later. Requires the user to be connected and running on macOS. ```go // Requires the user to be connected and running on macOS. if err := b.ConfigureAppleMail(ctx, userID, "alias@proton.me"); err != nil { log.Println("Apple Mail configuration failed:", err) } ``` -------------------------------- ### Fetch and Configure GoogleTest Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt Fetches the GoogleTest framework using FetchContent, specifically targeting a commit hash for reproducibility. It sets a policy for CMake version 3.24.0+ and forces the use of shared CRT on Windows to prevent build issues. ```cmake if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) # avoid warning DOWNLOAD_EXTRACT_TIMESTAMP endif () include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/b796f7d44681514f58a683a3a71ff17c94edb0c1.zip ) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() ``` -------------------------------- ### Run the Bridge GUI Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Launches the Proton Bridge GUI executable. It will attempt to locate the 'bridge' executable in the working directory, application directory, or specific relative paths. ```bash ./bridge-gui ``` -------------------------------- ### Run Bridge GUI with Custom Bridge Path Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Launches the Proton Bridge GUI and specifies the path to the bridge executable using the -b or --bridge-exe-path command-line parameter. ```bash ./bridge-gui -b "~/bin/bridge" ``` -------------------------------- ### Lint the Whole Project Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Run the linter across the entire project to check for code style and potential issues. ```bash make lint ``` -------------------------------- ### RunEventStream - C++/Qt Client Pseudo-code Source: https://context7.com/protonmail/proton-bridge/llms.txt Illustrates how a C++/Qt client might consume the event stream using generated gRPC stubs. It handles different event types like login and update events. ```C++ // C++ / Qt client example (pseudo-code using generated gRPC stubs): // grpc::ClientContext ctx; // EventStreamRequest req; // req.set_clientplatform("Qt/6.5 Windows"); // auto stream = stub->RunEventStream(&ctx, req); // StreamEvent event; // while (stream->Read(&event)) { // switch (event.event_case()) { // case StreamEvent::kLogin: // handleLoginEvent(event.login()); // break; // case StreamEvent::kUpdate: // handleUpdateEvent(event.update()); // break; // // ... // } // } ``` -------------------------------- ### Build the Project Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridge-gui/README.md Executes the build script to compile the Proton Bridge GUI application. This script typically runs the appropriate CMake commands. ```bash ./build.sh ``` -------------------------------- ### Build Proton Mail Bridge without GUI Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Use this command to build the Bridge app without Qt dependencies, resulting in a smaller binary. ```bash make build-nogui ```