### 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) } ``` -------------------------------- ### 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) } ``` -------------------------------- ### 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) } ``` ``` -------------------------------- ### 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 ``` -------------------------------- ### 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) } ``` -------------------------------- ### 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()) // ... } ``` ``` -------------------------------- ### 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 ``` -------------------------------- ### 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 ``` -------------------------------- ### 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 ``` -------------------------------- ### 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 ``` -------------------------------- ### 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 ``` -------------------------------- ### Generate gRPC/Protobuf C++ Code Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt Configures a custom command to generate C++ source and header files for gRPC and Protobuf services using protoc. Ensure PROTOC_EXE and GRPC_CPP_PLUGIN are correctly set in your environment. ```cmake set(FOCUS_PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../focus/proto") set(FOCUS_PROTO_FILE "${FOCUS_PROTO_DIR}/focus.proto") set(FOCUS_GRPC_OUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bridgepp/FocusGRPC") set(FOCUS_PROTO_CPP_FILE "${FOCUS_GRPC_OUT_DIR}/focus.pb.cc") set(FOCUS_PROTO_H_FILE "${FOCUS_GRPC_OUT_DIR}/focus.pb.h") set(FOCUS_GRPC_CPP_FILE "${FOCUS_GRPC_OUT_DIR}/focus.grpc.pb.cc") set(FOCUS_GRPC_H_FILE "${FOCUS_GRPC_OUT_DIR}/focus.grpc.pb.h") add_custom_command( OUTPUT ${FOCUS_PROTO_CPP_FILE} ${FOCUS_PROTO_H_FILE} ${FOCUS_GRPC_CPP_FILE} ${FOCUS_GRPC_H_FILE} COMMAND ${PROTOC_EXE} ARGS --proto_path=${FOCUS_PROTO_DIR} --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN}" --cpp_out=${FOCUS_GRPC_OUT_DIR} --grpc_out=${FOCUS_GRPC_OUT_DIR} ${FOCUS_PROTO_FILE} DEPENDS ${FOCUS_PROTO_FILE} COMMENT "Generating focus gPRC/Protobuf Focus service C++ code" ) ``` -------------------------------- ### Configure Automatic Updates Source: https://context7.com/protonmail/proton-bridge/llms.txt Enable or disable silent automatic updates and switch between update channels (e.g., stable, early-access). ```go // Enable automatic silent updates. if err := b.SetAutoUpdate(true); err != nil { log.Println("failed to enable auto-update:", err) } // Switch to the early-access (beta) channel. if err := b.SetUpdateChannel(updater.EarlyChannel); err != nil { log.Println("failed to switch to early channel:", err) } ``` -------------------------------- ### Query User Information with Bridge.GetUserIDs and Bridge.GetUserInfo Source: https://context7.com/protonmail/proton-bridge/llms.txt Retrieves a list of all tracked user IDs and then fetches detailed information for a specific user, including their username, addresses, state, and storage usage. Useful for managing multiple accounts. ```go ids := b.GetUserIDs() for _, id := range ids { info, err := b.GetUserInfo(id) if err != nil { log.Printf("error fetching info for %s: %v", id, err) continue } stateLabel := map[bridge.UserState]string{ bridge.SignedOut: "signed-out", bridge.Locked: "locked", bridge.Connected: "connected", }[info.State] log.Printf("user=%s email=%v state=%s usedBytes=%d maxBytes=%d bridgePass=%x", info.Username, info.Addresses, stateLabel, info.UsedSpace, info.MaxSpace, info.BridgePass) } ``` -------------------------------- ### Configure SMTP SSL Mode Source: https://context7.com/protonmail/proton-bridge/llms.txt Enable or disable SSL for SMTP connections. ```go if err := b.SetSMTPSSL(ctx, true); err != nil { log.Println("failed to enable SMTP SSL:", err) } ``` -------------------------------- ### Define bridgepp Library Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt Defines the main bridgepp library, listing all its source and header files, including generated Protobuf/gRPC files. It also specifies public include directories and links against necessary libraries like Qt6, protobuf, and gRPC. ```cmake add_library(bridgepp bridgepp/BugReportFlow/BugReportFlow.cpp bridgepp/BugReportFlow/BugReportFlow.h bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h bridgepp/CLI/CLIUtils.cpp bridgepp/CLI/CLIUtils.h bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h bridgepp/GRPC/GRPCErrors.h bridgepp/GRPC/GRPCErrors.cpp bridgepp/GRPC/EventFactory.cpp bridgepp/GRPC/EventFactory.h bridgepp/GRPC/GRPCConfig.cpp bridgepp/GRPC/GRPCConfig.h bridgepp/GRPC/GRPCUtils.cpp bridgepp/GRPC/GRPCUtils.h ${PROTO_CPP_FILE} ${PROTO_H_FILE} ${GRPC_CPP_FILE} ${GRPC_H_FILE} ${FOCUS_PROTO_CPP_FILE} ${FOCUS_PROTO_H_FILE} ${FOCUS_GRPC_CPP_FILE} ${FOCUS_GRPC_H_FILE} bridgepp/FocusGRPC/FocusGRPCClient.cpp bridgepp/FocusGRPC/FocusGRPCClient.h bridgepp/Log/Log.h bridgepp/Log/Log.cpp bridgepp/Log/LogUtils.h bridgepp/Log/LogUtils.cpp bridgepp/ProcessMonitor.cpp bridgepp/ProcessMonitor.h bridgepp/SessionID/SessionID.cpp bridgepp/SessionID/SessionID.h bridgepp/User/User.cpp bridgepp/User/User.h bridgepp/Worker/Worker.h bridgepp/Worker/Overseer.h bridgepp/Worker/Overseer.cpp) target_include_directories(bridgepp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(bridgepp Qt6::Core protobuf::libprotobuf gRPC::grpc++ ) target_precompile_headers(bridgepp PRIVATE Pch.h) ``` -------------------------------- ### Create PowerShell Profile File Source: https://github.com/protonmail/proton-bridge/blob/master/utils/remove-bridge/README.md This command checks if a PowerShell profile file exists and creates it if it doesn't. Replace `` with the actual profile path, or use `$PROFILE` for the current user and host. ```powershell if (!(Test-Path -Path )) { New-Item -ItemType File -Path -Force } ``` ```powershell if (!(Test-Path -Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force } ``` -------------------------------- ### Bridge.LoginFull Source: https://context7.com/protonmail/proton-bridge/llms.txt A convenience function that executes the complete multi-step login process in a single call. It utilizes provided callbacks to handle optional TOTP and mailbox password prompts. ```APIDOC ## Bridge.LoginFull — single-call login with callbacks Convenience wrapper that runs the entire multi-step login flow (credentials → optional TOTP → optional mailbox password) using caller-supplied callbacks. ### Method ```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 ) ``` ### Parameters - `ctx` (context.Context): The context for the request. - `username` (string): The user's email address. - `password` ([]byte): The user's password. - `totpCallback` (func() (string, error)): A callback function to provide the TOTP code when required. - `mailboxPasswordCallback` (func() ([]byte, error)): A callback function to provide the mailbox password when required for two-password accounts. ### Response - `userID` (string): The unique identifier for the logged-in user. - `err` (error): An error if the login process fails. ``` -------------------------------- ### Submit Bug Report with Logs Source: https://context7.com/protonmail/proton-bridge/llms.txt Use this function to submit a bug report to Proton support. It automatically collects recent logs, zips them, and sends the report. Attachments beyond the first are uploaded asynchronously. ```go err := b.ReportBug(ctx, &bridge.ReportBugReq{ OSType: "Linux", OSVersion: "Ubuntu 22.04", Title: "IMAP sync stalls after sleep", Description: "After the laptop wakes from sleep, new emails do not appear for ~10 minutes.", Username: "user@proton.me", Email: "user@proton.me", EmailClient: "Thunderbird/115", IncludeLogs: true, }) if err != nil { log.Println("bug report failed:", err) } else { log.Println("bug report submitted successfully") } ``` -------------------------------- ### Bridge.GetIMAPSSL / Bridge.SetIMAPSSL Source: https://context7.com/protonmail/proton-bridge/llms.txt Controls the IMAP SSL/STARTTLS mode. `GetIMAPSSL` checks the current setting, and `SetIMAPSSL` enables or disables SSL (TLS on connect) in favor of STARTTLS. ```APIDOC ## Bridge.GetIMAPSSL / Bridge.SetIMAPSSL — IMAP SSL/STARTTLS mode ```go // Check current SSL setting isSSL := 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) } ``` ### Methods - `GetIMAPSSL() bool`: Returns `true` if SSL is enabled, `false` otherwise. - `SetIMAPSSL(ctx context.Context, enable bool)`: Sets the IMAP SSL mode. ### Parameters (SetIMAPSSL) - `ctx` (context.Context): The context for the request. - `enable` (bool): `true` to enable SSL, `false` to use STARTTLS. ``` -------------------------------- ### Define bridgepp-test Executable Source: https://github.com/protonmail/proton-bridge/blob/master/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt Defines the bridgepp-test executable for running unit tests. It lists the test source files, adds a dependency on the bridgepp library, links against GTest and bridgepp, and discovers tests using the gtest_discover_tests command. ```cmake add_executable(bridgepp-test EXCLUDE_FROM_ALL Test/TestBridgeUtils.cpp Test/TestBugReportFlow.cpp Test/TestBugReportFlow.h Test/TestCLI.cpp Test/TestException.cpp Test/TestSessionID.cpp Test/TestWorker.cpp Test/TestWorker.h ) add_dependencies(bridgepp-test bridgepp) target_precompile_headers(bridgepp-test PRIVATE Pch.h) target_link_libraries(bridgepp-test GTest::gtest_main bridgepp ) include(GoogleTest) gtest_discover_tests(bridgepp-test) ``` -------------------------------- ### Authenticate Credentials with Bridge.LoginAuth Source: https://context7.com/protonmail/proton-bridge/llms.txt Authenticates user credentials against the Proton API. Handles potential errors like wrong password or required paid plan. It's the first step in a multi-step login process. ```go import ( "context" "log" protonapi "github.com/ProtonMail/go-proton-api" ) // Step 1 – authenticate credentials. client, auth, err := b.LoginAuth(ctx, "user@proton.me", []byte("password"), nil) if err != nil { // Inspect API error code for finer-grained handling. var apiErr *protonapi.APIError if errors.As(err, &apiErr) { switch apiErr.Code { case protonapi.PasswordWrong: log.Println("wrong password") case protonapi.PaidPlanRequired: log.Println("Proton Mail Bridge requires a paid plan") } } log.Fatal(err) } // Step 2 – handle 2FA if required. if auth.TwoFA.Enabled&protonapi.HasTOTP != 0 { totp := promptTOTP() if err := client.Auth2FA(ctx, protonapi.Auth2FAReq{TwoFactorCode: totp}); err != nil { log.Fatal("2FA failed:", err) } } // Step 3 – resolve the mailbox (key) password. keyPass := []byte("password") if auth.PasswordMode == protonapi.TwoPasswordMode { keyPass = []byte(promptMailboxPassword()) } // Step 4 – finalize login and store the user session. userID, err := b.LoginUser(ctx, client, auth, keyPass, nil) if err != nil { log.Fatal("login failed:", err) } log.Println("logged in user:", userID) ``` -------------------------------- ### Display PowerShell Profile Path Source: https://github.com/protonmail/proton-bridge/blob/master/utils/remove-bridge/README.md Use this command to display the path to your PowerShell profile file, which is where you can add script directories to be loaded automatically. ```powershell PS C:\Users\Gjorgji> Write-Output $PROFILE C:\Users\Gjorgji\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 PS C:\Users\Gjorgji> ``` -------------------------------- ### Login / Login2FA / Login2Passwords Source: https://context7.com/protonmail/proton-bridge/llms.txt Handles the gRPC login flow for user authentication. Supports standard login, two-factor authentication (2FA), and two-password authentication. ```APIDOC ## Login / Login2FA / Login2Passwords — gRPC login flow ### Description Initiates the user login process. The password must be base64-encoded before sending. Supports standard login, 2FA, and two-password flows. ### Method POST (implied by gRPC) ### Endpoint /protonbridge.Bridge/Login /protonbridge.Bridge/Login2FA /protonbridge.Bridge/Login2Passwords ### Parameters #### Request Body (LoginRequest) - **username** (string) - Required - The user's Proton username. - **password** (bytes) - Required - The base64-encoded password or TOTP code. ### Request Example (Login) ```go import ( "encoding/base64" pb "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" "golang.org/x/net/context" ) ctx := context.Background() password := "my-password" encPassword := base64.StdEncoding.EncodeToString([]byte(password)) _, err := client.Login(ctx, &pb.LoginRequest{ Username: "user@proton.me", Password: []byte(encPassword), }) ``` ### Request Example (Login2FA) ```go // If the server sends LoginTfaRequestedEvent via the event stream: totp := "123456" totpEnc := base64.StdEncoding.EncodeToString([]byte(totp)) _, err = client.Login2FA(ctx, &pb.LoginRequest{ Username: "user@proton.me", Password: []byte(totpEnc), }) ``` ### Response #### Success Response (200 OK) Typically an empty response or a success indicator. Errors are handled via gRPC status codes. ``` -------------------------------- ### Bridge.LoginAuth Source: https://context7.com/protonmail/proton-bridge/llms.txt Initiates the login flow by authenticating credentials against the Proton API. It returns an authorized client and an Auth token, which may indicate the need for further authentication steps like TOTP 2FA, FIDO2, or a second mailbox password before calling LoginUser. ```APIDOC ## Bridge.LoginAuth — begin the login flow Authenticates credentials against the Proton API and returns an authorized client plus an `Auth` token. The returned `Auth` indicates whether TOTP 2FA, FIDO2, or a second mailbox password is required before calling `LoginUser`. ### Method ```go client, auth, err := b.LoginAuth(ctx, "user@proton.me", []byte("password"), nil) ``` ### Parameters - `ctx` (context.Context): The context for the request. - `username` (string): The user's email address. - `password` ([]byte): The user's password. - `opts` (*LoginAuthOpts): Optional parameters. ### Response - `client` (*protonapi.APIClient): An authorized client. - `auth` (*protonapi.Auth): Authentication details, including 2FA requirements. - `err` (error): An error if the authentication fails. ### Error Handling Handles specific API errors like `PasswordWrong` and `PaidPlanRequired`. ### Related Operations - `LoginUser`: Finalizes the login process. - `Auth2FA`: Handles two-factor authentication. ``` -------------------------------- ### Unset MSYSTEM Variable on Windows Source: https://github.com/protonmail/proton-bridge/blob/master/BUILDS.md Before building on Windows, unset the MSYSTEM variable to ensure a correct build environment. ```bash export MSYSTEM= ``` -------------------------------- ### Configure IMAP Port with Bridge.GetIMAPPort and Bridge.SetIMAPPort Source: https://context7.com/protonmail/proton-bridge/llms.txt Enables reading and modifying the local IMAP server port. Changing the port will automatically restart the IMAP server. The default port is 1143. ```go currentPort := b.GetIMAPPort() log.Println("IMAP listening on port", currentPort) // default: 1143 if err := b.SetIMAPPort(ctx, 1144); err != nil { log.Println("failed to set IMAP port:", err) } ``` -------------------------------- ### Perform Factory Reset Source: https://context7.com/protonmail/proton-bridge/llms.txt Wipes all local user data, including user sessions and local files, except for the vault encryption key. This action is irreversible and deletes all locally synced mail data. ```go // WARNING: irreversible – all synced mail data is deleted locally. b.FactoryReset(ctx) ``` -------------------------------- ### Bridge.GetIMAPPort / Bridge.SetIMAPPort Source: https://context7.com/protonmail/proton-bridge/llms.txt Manages the local IMAP server port configuration. `GetIMAPPort` retrieves the current port, while `SetIMAPPort` changes it and automatically restarts the IMAP server. ```APIDOC ## Bridge.GetIMAPPort / Bridge.SetIMAPPort — IMAP port configuration Reads or changes the local IMAP port. Changing the port triggers an automatic IMAP server restart. ### Methods - `GetIMAPPort() int`: Returns the current IMAP port. - `SetIMAPPort(ctx context.Context, port int)`: Sets the IMAP port. ### Parameters (SetIMAPPort) - `ctx` (context.Context): The context for the request. - `port` (int): The desired IMAP port number. ### Response (SetIMAPPort) - `err` (error): An error if setting the IMAP port fails. ### Default Port - The default IMAP port is 1143. ``` -------------------------------- ### SetMailServerSettings / MailServerSettings Source: https://context7.com/protonmail/proton-bridge/llms.txt Configures and retrieves IMAP/SMTP server settings, including ports and SSL usage. ```APIDOC ## SetMailServerSettings / MailServerSettings — gRPC port & SSL configuration ### Description Allows retrieval and modification of IMAP and SMTP server settings, including port numbers and SSL/TLS configuration. ### Method GET (MailServerSettings), POST (SetMailServerSettings - implied by gRPC) ### Endpoint /protonbridge.Bridge/MailServerSettings /protonbridge.Bridge/SetMailServerSettings ### Parameters #### MailServerSettings Request - None (uses `emptypb.Empty`) #### SetMailServerSettings Request Body (ImapSmtpSettings) - **imapPort** (int32) - Optional - The IMAP port number. - **smtpPort** (int32) - Optional - The SMTP port number. - **useSSLForImap** (bool) - Optional - Whether to use SSL/TLS for IMAP. - **useSSLForSmtp** (bool) - Optional - Whether to use SSL/TLS for SMTP. ### Request Example (Read Settings) ```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() 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) ``` ### Request Example (Set Settings) ```go // 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. ``` ### Response #### Success Response (MailServerSettings) - **imapPort** (int32) - The configured IMAP port. - **smtpPort** (int32) - The configured SMTP port. - **useSSLForImap** (bool) - Indicates if SSL/TLS is used for IMAP. - **useSSLForSmtp** (bool) - Indicates if SSL/TLS is used for SMTP. #### Success Response (SetMailServerSettings) Typically an empty response or a success indicator. A `ChangeMailServerSettingsFinishedEvent` will be sent on the event stream. ``` -------------------------------- ### Manage User Sessions with Bridge.LogoutUser and Bridge.DeleteUser Source: https://context7.com/protonmail/proton-bridge/llms.txt Provides methods to manage user sessions. `LogoutUser` ends the current API session while preserving local data, allowing for re-login. `DeleteUser` performs a full removal, purging both the session and local data. ```go // Logout (session ends, data preserved for re-login). if err := b.LogoutUser(ctx, userID); err != nil { log.Println("logout error:", err) } // Full removal (session + local data). if err := b.DeleteUser(ctx, userID); err != nil { log.Println("delete error:", err) } ``` -------------------------------- ### Configure Address Mode with Bridge.SetAddressMode Source: https://context7.com/protonmail/proton-bridge/llms.txt Allows switching between 'combined mode' (all addresses in one inbox) and 'split mode' (each address as a separate IMAP account). This configuration affects how addresses are presented to IMAP clients. ```go import "github.com/ProtonMail/proton-bridge/v3/internal/vault" // Switch to split mode (each address is a separate IMAP login). if err := b.SetAddressMode(ctx, userID, vault.SplitMode); err != nil { log.Println("failed to set split mode:", err) } // Switch back to combined mode. if err := b.SetAddressMode(ctx, userID, vault.CombinedMode); err != nil { log.Println("failed to set combined mode:", err) } ``` -------------------------------- ### Manage DNS-over-HTTPS (DoH) Setting Source: https://context7.com/protonmail/proton-bridge/llms.txt Checks the current DoH status and enables it if disabled. When enabled, Bridge uses DoH to reach the Proton API if the standard DNS path is blocked. ```go log.Println("DoH enabled:", b.GetProxyAllowed()) if err := b.SetProxyAllowed(true); err != nil { log.Println("failed to enable DoH:", err) } ``` -------------------------------- ### Check for Bridge Updates Source: https://context7.com/protonmail/proton-bridge/llms.txt Initiates an asynchronous check for available updates. Subscribe to update-related events before triggering the check to receive results. ```go // Subscribe to update-related events before triggering the check. updateCh, cancel := b.GetEvents( events.UpdateAvailable{}, events.UpdateNotAvailable{}, events.UpdateCheckFailed{}, ) def cancel() cancel() b.CheckForUpdates() switch ev := (<-updateCh).(type) { case events.UpdateAvailable: log.Printf("update available: version=%s silent=%v compatible=%v", ev.Release.Version, ev.Silent, ev.Compatible) case events.UpdateNotAvailable: log.Println("already on latest version") case events.UpdateCheckFailed: log.Println("update check failed:", ev.Error) } ``` -------------------------------- ### Automatic Update Configuration Source: https://context7.com/protonmail/proton-bridge/llms.txt Enables or disables silent automatic updates and allows switching between update channels (e.g., stable, early-access). ```APIDOC ## Bridge.SetAutoUpdate / Bridge.SetUpdateChannel — enable/disable silent updates ### Description Allows enabling or disabling silent automatic updates and switching to different update channels. ### Methods - `SetAutoUpdate(enable bool)` - `SetUpdateChannel(channel updater.Channel)` ### Request Example ```go // Enable automatic silent updates. if err := b.SetAutoUpdate(true); err != nil { log.Println("failed to enable auto-update:", err) } // Switch to the early-access (beta) channel. if err := b.SetUpdateChannel(updater.EarlyChannel); err != nil { log.Println("failed to switch to early channel:", err) } ``` ``` -------------------------------- ### Relocate Local Email Cache Source: https://context7.com/protonmail/proton-bridge/llms.txt Moves the local email cache (IMAP state database) to a new path. This operation pauses user event loops during the move. ```go if err := b.SetGluonDir(ctx, "/mnt/fast-ssd/proton-bridge-cache"); err != nil { log.Println("failed to move gluon cache:", err) } ``` -------------------------------- ### Subscribe to Bridge Events Source: https://context7.com/protonmail/proton-bridge/llms.txt Subscribe to specific typed bridge events by passing event types to `GetEvents`. A `CancelFunc` is returned to unregister the watcher. Pass no arguments to receive all events. ```go import "github.com/ProtonMail/proton-bridge/v3/internal/events" // Subscribe to connectivity and sync events for a specific user. ch, cancel := b.GetEvents( events.ConnStatusUp{}, events.ConnStatusDown{}, events.SyncStarted{}, events.SyncFinished{}, ) def cancel() cancel() for ev := range ch { switch e := ev.(type) { case events.ConnStatusUp: log.Println("API connection restored") case events.ConnStatusDown: log.Println("API connection lost") case events.SyncStarted: log.Printf("sync started for user %s", e.UserID) case events.SyncFinished: log.Printf("sync finished for user %s", e.UserID) } } ```